Skip to content

Commit

Permalink
feat: cascader-view support fieldNames
Browse files Browse the repository at this point in the history
  • Loading branch information
1587315093 committed Jul 11, 2023
1 parent e286ab7 commit 2c01ef7
Show file tree
Hide file tree
Showing 8 changed files with 1,195 additions and 21 deletions.
49 changes: 28 additions & 21 deletions src/components/cascader-view/cascader-view.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,15 @@ import { useConfig } from '../config-provider'
import { optionSkeleton } from './option-skeleton'
import Skeleton from '../skeleton'
import { useUpdateEffect } from 'ahooks'
import { useFieldNames } from '../../hooks'
import type { FieldNamesType } from '../../hooks'

const classPrefix = `adm-cascader-view`

export type CascaderValue = string

export type CascaderOption = {
label: string
value: string
disabled?: boolean
children?: CascaderOption[]
[key: string]: any
}

export type CascaderValueExtend = {
Expand All @@ -36,47 +35,49 @@ export type CascaderViewProps = {
onTabsChange?: (index: number) => void
activeIcon?: ReactNode
loading?: boolean
fieldNames?: FieldNamesType
} & NativeProps<'--height'>

const defaultProps = {
defaultValue: [],
}

export const CascaderView: FC<CascaderViewProps> = p => {
const { locale } = useConfig()
const props = mergeProps(defaultProps, p)
const placeholder = props.placeholder || locale.Cascader.placeholder

const { locale } = useConfig()
const generateValueExtend = useCascaderValueExtend(props.options)
const [labelName, valueName, disabledName, childrenName] = useFieldNames(
props.fieldNames
)

const [value, setValue] = usePropsValue({
...props,
onChange: val => {
props.onChange?.(val, generateValueExtend(val))
},
})
const [tabActiveIndex, setTabActiveIndex] = useState<number>(0)
useUpdateEffect(() => {
props.onTabsChange?.(tabActiveIndex)
}, [tabActiveIndex])

const generateValueExtend = useCascaderValueExtend(props.options)
const [tabActiveIndex, setTabActiveIndex] = useState(0)

const levels = useMemo(() => {
const ret: {
selected: CascaderOption | undefined
options: CascaderOption[]
}[] = []

let currentOptions = props.options
let reachedEnd = false
for (const v of value) {
const target = currentOptions.find(option => option.value === v)
const target = currentOptions.find(option => option[valueName] === v)
ret.push({
selected: target,
options: currentOptions,
})
if (!target || !target.children) {
if (!target || !target[childrenName]) {
reachedEnd = true
break
}
currentOptions = target.children
currentOptions = target[childrenName]
}
if (!reachedEnd) {
ret.push({
Expand All @@ -87,6 +88,9 @@ export const CascaderView: FC<CascaderViewProps> = p => {
return ret
}, [value, props.options])

useUpdateEffect(() => {
props.onTabsChange?.(tabActiveIndex)
}, [tabActiveIndex])
useEffect(() => {
setTabActiveIndex(levels.length - 1)
}, [value])
Expand All @@ -104,9 +108,12 @@ export const CascaderView: FC<CascaderViewProps> = p => {
}
setValue(next)
}

const whetherLoading = <T extends unknown[]>(options: T) =>
props.loading || options === optionSkeleton

const placeholder = props.placeholder || locale.Cascader.placeholder

return withNativeProps(
props,
<div className={classPrefix}>
Expand All @@ -127,7 +134,7 @@ export const CascaderView: FC<CascaderViewProps> = p => {
title={
<div className={`${classPrefix}-header-title`}>
{selected
? selected.label
? selected[labelName]
: typeof placeholder === 'function'
? placeholder(index)
: placeholder}
Expand Down Expand Up @@ -164,17 +171,17 @@ export const CascaderView: FC<CascaderViewProps> = p => {
activeIcon={props.activeIcon}
>
{level.options.map(option => {
const active = value[index] === option.value
const active = value[index] === option[valueName]
return (
<CheckList.Item
value={option.value}
key={option.value}
disabled={option.disabled}
value={option[valueName]}
key={option[valueName]}
disabled={option[disabledName]}
className={classNames(`${classPrefix}-item`, {
[`${classPrefix}-item-active`]: active,
})}
>
{option.label}
{option[labelName]}
</CheckList.Item>
)
})}
Expand Down
1 change: 1 addition & 0 deletions src/components/cascader-view/index.en.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ CascaderView is the content area of [Cascader](/components/cascader).
| --- | --- | --- | --- |
| activeIcon | The icon displayed when selected | `ReactNode` | - |
| defaultValue | Default selected options | `CascaderValue[]` | `[]` |
| fieldNames | Custom field name for label and value and disabled and children | `{ label: string, value: string, disabled: string, children: string }` | `{ label: 'label', value: 'value',disabled:'disabled', children: 'children' }` |
| onChange | Triggered when the selected options are changed | `(value: CascaderValue[], extend: CascaderValueExtend) => void` | - |
| onTabsChange | Callback when switching panel | `(index: number) => void` | - |
| options | Data of the cascade options | `CascaderOption[]` | - |
Expand Down
1 change: 1 addition & 0 deletions src/components/cascader-view/index.zh.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ CascaderView 是 [Cascader](/zh/components/cascader) 的内容区域。
| --- | --- | --- | --- |
| activeIcon | 选中图标 | `ReactNode` | - |
| defaultValue | 默认选中项 | `CascaderValue[]` | `[]` |
| fieldNames | 自定义 options 中 label value disabled children 的字段 | `{ label: string, value: string, disabled: string, children: string }` | `{ label: 'label', value: 'value',disabled:'disabled', children: 'children' }` |
| onChange | 选项改变时触发 | `(value: CascaderValue[], extend: CascaderValueExtend) => void` | - |
| onTabsChange | 切换面板的回调 | `(index: number) => void` | - |
| options | 配置每一列的选项 | `CascaderOption[]` | - |
Expand Down
Loading

0 comments on commit 2c01ef7

Please sign in to comment.