first commit

This commit is contained in:
lingxiao865
2026-02-10 08:05:03 +08:00
commit c5af079d8c
1094 changed files with 97530 additions and 0 deletions

View File

@@ -0,0 +1,56 @@
:: BASE_DOC ::
## API
### Cascader Props
name | type | default | description | required
-- | -- | -- | -- | --
custom-style | Object | - | CSS(Cascading Style Sheets) | N
check-strictly | Boolean | false | \- | N
close-btn | Boolean | true | \- | N
keys | Object | - | Typescript: `CascaderKeysType` `type CascaderKeysType = TreeKeysType`。[see more ts definition](https://github.com/tencent/tdesign-miniprogram/blob/develop/packages/uniapp-components/common/common.ts)。[see more ts definition](https://github.com/tencent/tdesign-miniprogram/blob/develop/packages/uniapp-components/cascader/type.ts) | N
options | Array | [] | Typescript: `Array<CascaderOption>` | N
placeholder | String | 选择选项 | \- | N
sub-titles | Array | [] | Typescript: `Array<string>` | N
theme | String | step | options: step/tab | N
title | String | - | \- | N
value | String / Number | - | `v-model:value` is supported | N
default-value | String / Number | - | uncontrolled property | N
visible | Boolean | false | \- | N
### Cascader Events
name | params | description
-- | -- | --
change | `(context: { value: string \| number, selectedOptions: string[] })` | \-
close | `(context: { trigger: CascaderTriggerSource })` | [see more ts definition](https://github.com/tencent/tdesign-miniprogram/blob/develop/packages/uniapp-components/cascader/type.ts)。<br/>`type CascaderTriggerSource = 'overlay' \| 'close-btn' \| 'finish'`<br/>
pick | `(context: { value: string \| number, label: string, index: number, level: number })` | \-
### Cascader Slots
name | Description
-- | --
close-btn | \-
header | \-
middle-content | \-
title | \-
### CSS Variables
The component provides the following CSS variables, which can be used to customize styles.
Name | Default Value | Description
-- | -- | --
--td-cascader-active-color | @brand-color | -
--td-cascader-bg-color | @bg-color-container | -
--td-cascader-border-color | @component-stroke | -
--td-cascader-content-height | 78vh | -
--td-cascader-disabled-color | @text-color-disabled | -
--td-cascader-options-height | calc(100% - @cascader-step-height) | -
--td-cascader-options-title-color | @text-color-placeholder | -
--td-cascader-step-arrow-color | @text-color-placeholder | -
--td-cascader-step-dot-size | 16rpx | -
--td-cascader-step-height | 88rpx | -
--td-cascader-title-color | @text-color-primary | -
--td-cascader-title-font | @font-title-large | -
--td-cascader-title-padding | @spacer-2 | -

View File

@@ -0,0 +1,96 @@
---
title: Cascader 级联选择器
description: 级联选择器适用于有清晰层级结构的数据集合,用户可以通过逐级查看并选择。
spline: form
isComponent: true
---
## 引入
可在 `main.ts` 或在需要使用的页面或组件中引入。
```js
import TCascader from '@tdesign/uniapp/cascader/cascader.vue';
```
### 基础用法
{{ base }}
### 选项卡风格
{{ theme-tab }}
### 进阶
#### 带初始值
{{ with-value }}
#### 自定义 keys
{{ keys }}
#### 使用次级标题
{{ with-title }}
#### 选择任意一项
{{ check-strictly }}
## API
### Cascader Props
名称 | 类型 | 默认值 | 描述 | 必传
-- | -- | -- | -- | --
custom-style | Object | - | 自定义样式 | N
check-strictly | Boolean | false | 父子节点选中状态不再关联,可各自选中或取消 | N
close-btn | Boolean | true | 关闭按钮 | N
keys | Object | - | 用来定义 value / label / children / disabled 在 `options` 中对应的字段别名。TS 类型:`CascaderKeysType` `type CascaderKeysType = TreeKeysType`。[通用类型定义](https://github.com/tencent/tdesign-miniprogram/blob/develop/packages/uniapp-components/common/common.ts)。[详细类型定义](https://github.com/tencent/tdesign-miniprogram/blob/develop/packages/uniapp-components/cascader/type.ts) | N
options | Array | [] | 可选项数据源。TS 类型:`Array<CascaderOption>` | N
placeholder | String | 选择选项 | 未选中时的提示文案 | N
sub-titles | Array | [] | 每级展示的次标题。TS 类型:`Array<string>` | N
theme | String | step | 展示风格。可选项step/tab | N
title | String | - | 标题 | N
value | String / Number | - | 选项值。支持语法糖 `v-model:value` | N
default-value | String / Number | - | 选项值。非受控属性 | N
visible | Boolean | false | 是否展示 | N
### Cascader Events
名称 | 参数 | 描述
-- | -- | --
change | `(context: { value: string \| number, selectedOptions: string[] })` | 值发生变更时触发
close | `(context: { trigger: CascaderTriggerSource })` | 关闭时触发。[详细类型定义](https://github.com/tencent/tdesign-miniprogram/blob/develop/packages/uniapp-components/cascader/type.ts)。<br/>`type CascaderTriggerSource = 'overlay' \| 'close-btn' \| 'finish'`<br/>
pick | `(context: { value: string \| number, label: string, index: number, level: number })` | 选择后触发
### Cascader Slots
名称 | 描述
-- | --
close-btn | 自定义 `close-btn` 显示内容
header | 头部
middle-content | 中间内容
title | 自定义 `title` 显示内容
### CSS Variables
组件提供了下列 CSS 变量,可用于自定义样式。
名称 | 默认值 | 描述
-- | -- | --
--td-cascader-active-color | @brand-color | -
--td-cascader-bg-color | @bg-color-container | -
--td-cascader-border-color | @component-stroke | -
--td-cascader-content-height | 78vh | -
--td-cascader-disabled-color | @text-color-disabled | -
--td-cascader-options-height | calc(100% - @cascader-step-height) | -
--td-cascader-options-title-color | @text-color-placeholder | -
--td-cascader-step-arrow-color | @text-color-placeholder | -
--td-cascader-step-dot-size | 16rpx | -
--td-cascader-step-height | 88rpx | -
--td-cascader-title-color | @text-color-primary | -
--td-cascader-title-font | @font-title-large | -
--td-cascader-title-padding | @spacer-2 | -

View File

@@ -0,0 +1,102 @@
.t-cascader {
display: flex;
flex-direction: column;
background-color: var(--td-cascader-bg-color, var(--td-bg-color-container, var(--td-font-white-1, #ffffff)));
color: var(--td-cascader-title-color, var(--td-text-color-primary, var(--td-font-gray-1, rgba(0, 0, 0, 0.9))));
border-radius: var(--td-radius-extraLarge, 24rpx) var(--td-radius-extraLarge, 24rpx) 0 0;
--td-radio-icon-checked-color: var(--td-cascader-active-color, var(--td-brand-color, var(--td-primary-color-7, #0052d9)));
--td-tab-item-active-color: var(--td-cascader-active-color, var(--td-brand-color, var(--td-primary-color-7, #0052d9)));
--td-tab-track-color: var(--td-cascader-active-color, var(--td-brand-color, var(--td-primary-color-7, #0052d9)));
}
.t-cascader__close-btn {
right: var(--td-spacer-2, 32rpx);
top: var(--td-spacer-2, 32rpx);
position: absolute;
}
.t-cascader__title {
position: relative;
font: var(--td-cascader-title-font, var(--td-font-title-large, 600 36rpx / 52rpx var(--td-font-family, PingFang SC, Microsoft YaHei, Arial Regular)));
text-align: center;
padding: var(--td-cascader-title-padding, var(--td-spacer-2, 32rpx));
}
.t-cascader__content {
width: 100%;
height: var(--td-cascader-content-height, 78vh);
display: flex;
flex-direction: column;
}
.t-cascader__options {
width: 100vw;
}
.t-cascader__options-title {
color: var(--td-cascader-options-title-color, var(--td-text-color-placeholder, var(--td-font-gray-3, rgba(0, 0, 0, 0.4))));
font: var(--td-font-body-medium, 28rpx / 44rpx var(--td-font-family, PingFang SC, Microsoft YaHei, Arial Regular));
padding-top: 40rpx;
padding-left: var(--td-spacer-2, 32rpx);
box-sizing: border-box;
}
.t-cascader__options-container {
flex: 1;
display: flex;
transition: all ease 0.3s;
}
.t-cascader__step {
display: flex;
align-items: center;
height: var(--td-cascader-step-height, 88rpx);
}
.t-cascader__steps {
padding: 0 32rpx 10rpx;
position: relative;
}
.t-cascader__steps::after {
content: '';
display: block;
position: absolute;
top: unset;
bottom: 0;
left: unset;
right: unset;
background-color: var(--td-cascader-border-color, var(--td-component-stroke, var(--td-gray-color-3, #e7e7e7)));
}
.t-cascader__steps::after {
height: 1px;
left: 0;
right: 0;
transform: scaleY(0.5);
}
.t-cascader__step-dot {
position: relative;
width: var(--td-cascader-step-dot-size, 16rpx);
height: var(--td-cascader-step-dot-size, 16rpx);
border-radius: 50%;
border: 2rpx solid var(--td-cascader-active-color, var(--td-brand-color, var(--td-primary-color-7, #0052d9)));
box-sizing: border-box;
}
.t-cascader__step-dot:not(.t-cascader__step-dot--last)::after {
content: '';
display: block;
position: absolute;
left: 50%;
top: calc(var(--td-cascader-step-dot-size, 16rpx) + 14rpx);
height: 36rpx;
width: 2rpx;
background: var(--td-cascader-active-color, var(--td-brand-color, var(--td-primary-color-7, #0052d9)));
transform: translateX(-50%);
}
.t-cascader__step-dot--active {
background: var(--td-cascader-active-color, var(--td-brand-color, var(--td-primary-color-7, #0052d9)));
border-color: var(--td-cascader-active-color, var(--td-brand-color, var(--td-primary-color-7, #0052d9)));
}
.t-cascader__step-label {
padding-left: var(--td-spacer-2, 32rpx);
font: var(--td-font-body-medium, 28rpx / 44rpx var(--td-font-family, PingFang SC, Microsoft YaHei, Arial Regular));
}
.t-cascader__step-label--active {
color: var(--td-cascader-active-color, var(--td-brand-color, var(--td-primary-color-7, #0052d9)));
font-weight: 600;
}
.t-cascader__step-arrow {
color: var(--td-cascader-step-arrow-color, var(--td-text-color-placeholder, var(--td-font-gray-3, rgba(0, 0, 0, 0.4))));
margin-left: auto;
}

View File

@@ -0,0 +1,519 @@
<template>
<view>
<TPopup
:class="tClass"
:visible="dataVisible"
placement="bottom"
@visible-change="onVisibleChange"
>
<view
:style="tools._style([customStyle])"
:class="name"
>
<view :class="name + '__title'">
<slot name="title" />
{{ title }}
</view>
<view
:class="name + '__close-btn'"
@click="onClose"
>
<slot name="close-btn" />
<TIcon
v-if="closeBtn"
size="48rpx"
name="close"
/>
</view>
<slot name="header" />
<view :class="name + '__content'">
<block v-if="steps && steps.length">
<view
v-if="theme == 'step'"
:class="name + '__steps'"
>
<view
v-for="(item, index) in steps"
:key="index"
:class="name + '__step'"
:data-index="index"
@click="() => onStepClick(index)"
>
<view
:class="
name +
'__step-dot ' +
name +
'__step-dot--' +
(item !== placeholder ? 'active' : '') +
' ' +
name +
'__step-dot--' +
(index === steps.length - 1 ? 'last' : '')
"
/>
<view :class="name + '__step-label ' + name + '__step-label--' + (index === stepIndex ? 'active' : '')">
{{ item }}
</view>
<TIcon
name="chevron-right"
size="44rpx"
:t-class="name + '__step-arrow'"
:custom-style="stepArrowCustomStyle"
style="margin-left: auto"
/>
</view>
</view>
<TTabs
v-if="theme == 'tab'"
ref="tabs"
:value="stepIndex"
:space-evenly="false"
@change="({value}) => onTabChange(value)"
>
<TTabPanel
v-for="(item, index) in steps"
:key="index"
:ref="`tab-${index}`"
:value="index"
:label="item"
/>
</TTabs>
</block>
<slot name="middle-content" />
<view
v-if="subTitles && subTitles[stepIndex]"
:class="name + '__options-title'"
>
{{ subTitles[stepIndex] }}
</view>
<view
:class="name + '__options-container'"
:style="'width: ' + (items.length + 1) + '00vw; transform: translateX(-' + stepIndex + '00vw)'"
>
<scroll-view
v-for="(options, index) in items"
:key="index"
:class="name + '__options'"
scroll-y
:scroll-top="scrollTopList[index]"
type="list"
:style="'height: ' + _optionsHeight + 'px'"
>
<view :class="'cascader-radio-group-' + index">
<TRadioGroup
:value="selectedValue[index]"
:keys="keys"
:options="options"
:data-level="index"
placement="right"
icon="line"
borderless
@change="({ value }) => handleSelect($event, { level: index, value })"
/>
</view>
</scroll-view>
</view>
</view>
</view>
</TPopup>
</view>
</template>
<script>
import TIcon from '../icon/icon';
import TPopup from '../popup/popup';
import TTabs from '../tabs/tabs';
import TTabPanel from '../tab-panel/tab-panel';
import TRadioGroup from '../radio-group/radio-group';
import { uniComponent } from '../common/src/index';
import { prefix } from '../common/config';
import props from './props';
import { getRect, coalesce, nextTick } from '../common/utils';
import tools from '../common/utils.wxs';
const name = `${prefix}-cascader`;
function parseOptions(options, keys) {
const label = coalesce(keys?.label, 'label');
const value = coalesce(keys?.value, 'value');
const disabled = coalesce(keys?.disabled, 'disabled');
return options.map(item => ({
[label]: item[label],
[value]: item[value],
[disabled]: item[disabled],
}));
}
const defaultState = {
contentHeight: 0,
stepHeight: 0,
tabsHeight: 0,
subTitlesHeight: 0,
stepsInitHeight: 0,
};
export default uniComponent({
name,
options: {
styleIsolation: 'shared',
},
controlledProps: [
{
key: 'value',
event: 'change',
},
],
externalClasses: [
`${prefix}-class`,
],
components: {
TIcon,
TPopup,
TTabs,
TTabPanel,
TRadioGroup,
},
props: {
...props,
},
emits: [
'update:visible',
],
data() {
return {
prefix,
name,
stepIndex: 0,
selectedIndexes: [],
selectedValue: [],
scrollTopList: [],
steps: [],
_optionsHeight: 0,
tools,
dataVisible: this.visible,
dataValue: coalesce(this.value, this.defaultValue),
items: [],
};
},
computed: {
stepArrowCustomStyle() {
return tools._style({
color: 'var(--td-cascader-step-arrow-color, var(--td-text-color-placeholder, var(--td-font-gray-3, rgba(0, 0, 0, .4))))',
marginLeft: 'auto',
});
},
},
watch: {
visible: {
handler(v) {
this.dataVisible = v;
},
immediate: true,
},
dataVisible: {
handler(v) {
if (v) {
nextTick().then(() => {
const $tabs = this.$refs.tabs;
$tabs?.setTrack();
$tabs?.getTabHeight().then((res) => {
this.state.tabsHeight = res.height;
});
});
// 不能使用 this.$nextTick在头条小程序下会报错
nextTick().then(() => {
this.initOptionsHeight(this.steps.length);
this.updateScrollTop();
this.initWithValue();
});
} else {
this.state = { ...defaultState };
}
},
immediate: true,
},
value: {
handler(v) {
this.dataValue = v;
},
immediate: true,
},
dataValue: {
handler() {
this.initWithValue();
},
immediate: true,
},
options: {
handler() {
const { selectedValue, steps, items } = this.genItems();
this.steps = steps;
this.items = items;
this.selectedValue = selectedValue;
this.stepIndex = items.length - 1;
this.setTabParent();
},
immediate: true,
deep: true,
},
selectedIndexes: {
handler() {
const { visible, theme } = this;
const { selectedValue, steps, items } = this.genItems();
this.steps = steps;
this.setTabParent();
this.selectedValue = selectedValue;
this.stepIndex = items.length - 1;
if (JSON.stringify(items) !== JSON.stringify(this.items)) {
this.items = items;
}
if (visible && theme === 'step') {
this.updateOptionsHeight(steps.length);
}
},
immediate: true,
deep: true,
},
stepIndex: {
handler() {
const { dataVisible: visible } = this;
if (visible) {
this.updateScrollTop();
}
},
immediate: true,
deep: true,
},
},
created() {
this.state = {
...defaultState,
};
},
mounted() {
},
methods: {
setTabParent() {
// #ifdef MP-TOUTIAO
nextTick().then(() => {
const tabsRef = this.$refs.tabs;
this.steps.forEach((tools, index) => {
const tabRef = this.$refs[`tab-${index}`];
tabRef?.[0]?.setParent(tabsRef);
});
});
// #endif
},
updateOptionsHeight(steps) {
const { contentHeight, stepsInitHeight, stepHeight, subTitlesHeight } = this.state;
this._optionsHeight = contentHeight - stepsInitHeight - subTitlesHeight - (steps - 1) * stepHeight;
},
async initOptionsHeight(steps) {
const { theme, subTitles } = this;
const { height } = await getRect(this, `.${name}__content`);
this.state.contentHeight = height;
if (theme === 'step') {
await Promise.all([
getRect(this, `.${name}__steps`),
getRect(this, `.${name}__step`),
])
.then(([stepsRect, stepRect]) => {
this.state.stepsInitHeight = stepsRect.height - (steps - 1) * stepRect.height;
this.state.stepHeight = stepRect.height;
})
.catch(() => {
});
}
if (subTitles.length > 0) {
const { height } = await getRect(this, `.${name}__options-title`);
this.state.subTitlesHeight = height;
}
const optionsInitHeight = this.state.contentHeight - this.state.subTitlesHeight;
this._optionsHeight = theme === 'step'
? optionsInitHeight - this.state.stepsInitHeight - (steps - 1) * this.state.stepHeight
: optionsInitHeight - this.state.tabsHeight;
},
initWithValue() {
if (this.dataValue != null && this.dataValue !== '') {
const selectedIndexes = this.getIndexesByValue(this.options, this.dataValue);
if (selectedIndexes) {
this.selectedIndexes = selectedIndexes;
}
} else {
this.selectedIndexes = [];
}
},
getIndexesByValue(options, value) {
const { keys } = this;
for (let i = 0, size = options.length; i < size; i += 1) {
const opt = options[i];
if (opt[coalesce(keys?.value, 'value')] === value) {
return [i];
}
if (opt[coalesce(keys?.children, 'children')]) {
const res = this.getIndexesByValue(opt[coalesce(keys?.children, 'children')], value);
if (res) {
return [i, ...res];
}
}
}
},
updateScrollTop() {
const { dataVisible: visible, items, selectedIndexes, stepIndex } = this;
if (visible) {
getRect(this, '.cascader-radio-group-0').then((rect) => {
const eachRadioHeight = rect.height / items[0]?.length;
this[`scrollTopList[${stepIndex}]`] = eachRadioHeight * selectedIndexes[stepIndex];
})
.catch(() => {
});
}
},
hide(trigger) {
this.dataVisible = false;
this.$emit('close', { trigger });
this.$emit('update:visible', false);
},
onVisibleChange() {
this.hide('overlay');
},
onClose() {
if (this.checkStrictly) {
this.triggerChange();
}
this.hide('close-btn');
},
onStepClick(index) {
this.stepIndex = index;
},
onTabChange(value) {
this.stepIndex = value;
},
genItems() {
const { options, selectedIndexes, keys, placeholder } = this;
const selectedValue = [];
const steps = [];
const items = [parseOptions(options, keys)];
if (options.length > 0) {
let current = options;
for (let i = 0, size = selectedIndexes.length; i < size; i += 1) {
const index = selectedIndexes[i];
const next = current[index];
current = next[coalesce(keys?.children, 'children')];
selectedValue.push(next[coalesce(keys?.value, 'value')]);
steps.push(next[coalesce(keys?.label, 'label')]);
if (next[coalesce(keys?.children, 'children')]) {
items.push(parseOptions(next[coalesce(keys?.children, 'children')], keys));
}
}
}
if (steps.length < items.length) {
steps.push(placeholder);
}
return {
selectedValue,
steps,
items,
};
},
handleSelect(tools, { level, value }) {
const { checkStrictly } = this;
const { selectedIndexes, items, keys, options, selectedValue } = this;
const index = items[level].findIndex(item => item[coalesce(keys?.value, 'value')] === value);
let item = selectedIndexes.slice(0, level).reduce((acc, item, index) => {
if (index === 0) {
return acc[item];
}
return acc[coalesce(keys?.children, 'children')][item];
}, options);
if (level === 0) {
item = item[index];
} else {
item = item[coalesce(keys?.children, 'children')][index];
}
if (item[coalesce(keys?.disabled, 'disabled')]) {
return;
}
this.$emit('pick', {
value: item[coalesce(keys?.value, 'value')],
label: item[coalesce(keys?.label, 'label')],
index,
level,
});
selectedIndexes[level] = index;
if (checkStrictly && selectedValue.includes(String(value))) {
selectedIndexes.length = level;
this.selectedIndexes = selectedIndexes;
return;
}
selectedIndexes.length = level + 1;
const { items: newItems } = this.genItems();
if (item?.[coalesce(keys?.children, 'children')]?.length >= 0) {
this.selectedIndexes = selectedIndexes;
this[`items[${level + 1}]`] = newItems[level + 1];
} else {
// setCascaderValue(item.value);
this.selectedIndexes = selectedIndexes;
setTimeout(this.triggerChange);
this.hide('finish');
}
},
triggerChange() {
const { items, selectedValue, selectedIndexes } = this;
this._trigger('change', {
value: coalesce(selectedValue[selectedValue.length - 1], ''),
selectedOptions: items.map((item, index) => item[selectedIndexes[index]]).filter(Boolean),
});
},
},
});
</script>
<style scoped>
@import './cascader.css';
</style>

View File

@@ -0,0 +1,73 @@
/* eslint-disable */
/**
* 该文件为脚本自动生成文件,请勿随意修改。如需修改请联系 PMC
* */
import type { TdCascaderProps } from './type';
export default {
/** 父子节点选中状态不再关联,可各自选中或取消 */
checkStrictly: Boolean,
/** 关闭按钮 */
closeBtn: {
type: Boolean,
default: true as TdCascaderProps['closeBtn'],
},
/** 用来定义 value / label / children / disabled 在 `options` 中对应的字段别名 */
keys: {
type: Object,
},
/** 可选项数据源 */
options: {
type: Array,
default: (): TdCascaderProps['options'] => [],
},
/** 未选中时的提示文案 */
placeholder: {
type: String,
default: '选择选项',
},
/** 每级展示的次标题 */
subTitles: {
type: Array,
default: (): TdCascaderProps['subTitles'] => [],
},
/** 展示风格 */
theme: {
type: String,
default: 'step' as TdCascaderProps['theme'],
validator(val: TdCascaderProps['theme']): boolean {
if (!val) return true;
return ['step', 'tab'].includes(val);
},
},
/** 标题 */
title: {
type: String,
},
/** 选项值 */
value: {
type: [String, Number],
},
/** 选项值,非受控属性 */
defaultValue: {
type: [String, Number],
},
/** 是否展示 */
visible: Boolean,
/** 值发生变更时触发 */
onChange: {
type: Function,
default: () => ({}),
},
/** 关闭时触发 */
onClose: {
type: Function,
default: () => ({}),
},
/** 选择后触发 */
onPick: {
type: Function,
default: () => ({}),
},
};

View File

@@ -0,0 +1,77 @@
/* eslint-disable */
/**
* 该文件为脚本自动生成文件,请勿随意修改。如需修改请联系 PMC
* */
import type { TreeOptionData, TreeKeysType } from '../common/common';
export interface TdCascaderProps<CascaderOption extends TreeOptionData = TreeOptionData> {
/**
* 父子节点选中状态不再关联,可各自选中或取消
* @default false
*/
checkStrictly?: boolean;
/**
* 关闭按钮
* @default true
*/
closeBtn?: boolean;
/**
* 用来定义 value / label / children / disabled 在 `options` 中对应的字段别名
*/
keys?: CascaderKeysType;
/**
* 可选项数据源
* @default []
*/
options?: Array<CascaderOption>;
/**
* 未选中时的提示文案
* @default 选择选项
*/
placeholder?: string;
/**
* 每级展示的次标题
* @default []
*/
subTitles?: Array<string>;
/**
* 展示风格
* @default step
*/
theme?: 'step' | 'tab';
/**
* 标题
*/
title?: string;
/**
* 选项值
*/
value?: string | number;
/**
* 选项值,非受控属性
*/
defaultValue?: string | number;
/**
* 是否展示
* @default false
*/
visible?: boolean;
/**
* 值发生变更时触发
*/
onChange?: (context: { value: string | number; selectedOptions: string[] }) => void;
/**
* 关闭时触发
*/
onClose?: (context: { trigger: CascaderTriggerSource }) => void;
/**
* 选择后触发
*/
onPick?: (context: { value: string | number; label: string; index: number; level: number }) => void;
}
export type CascaderKeysType = TreeKeysType;
export type CascaderTriggerSource = 'overlay' | 'close-btn' | 'finish';