diff --git a/src/components/cascader-view/cascader-view.tsx b/src/components/cascader-view/cascader-view.tsx index ae2942b705..90d5c3d749 100644 --- a/src/components/cascader-view/cascader-view.tsx +++ b/src/components/cascader-view/cascader-view.tsx @@ -12,15 +12,12 @@ import { optionSkeleton } from './option-skeleton' import Skeleton from '../skeleton' import { useUpdateEffect } from 'ahooks' import { useFieldNames } from '../../hooks' -import type { FieldNamesType } from '../../hooks' +import type { FieldNamesType, BaseOptionType } from '../../hooks' const classPrefix = `adm-cascader-view` export type CascaderValue = string -type BaseOptionType = { - [key: string]: any -} export type CascaderOption = { label?: string value?: string diff --git a/src/components/selector/demos/demo1.tsx b/src/components/selector/demos/demo1.tsx index c5cf7b5437..e2c8d20dd1 100644 --- a/src/components/selector/demos/demo1.tsx +++ b/src/components/selector/demos/demo1.tsx @@ -1,7 +1,7 @@ import React from 'react' import { Selector, Space } from 'antd-mobile' import { DemoBlock } from 'demos' -import { options } from './options' +import { options, fieldNamesOptions } from './options' export default () => { return ( @@ -18,7 +18,7 @@ export default () => { console.log(arr, extend.items)} /> @@ -28,7 +28,7 @@ export default () => { columns={2} options={options} defaultValue={['2', '3']} - multiple={true} + multiple /> @@ -37,13 +37,13 @@ export default () => { columns={3} options={options} defaultValue={['2', '3']} - multiple={true} + multiple /> - + { /> + + console.log(arr, extend.items)} + /> + ) } diff --git a/src/components/selector/demos/options.tsx b/src/components/selector/demos/options.tsx index 7bc5199d03..2cc8ebf8c3 100644 --- a/src/components/selector/demos/options.tsx +++ b/src/components/selector/demos/options.tsx @@ -12,3 +12,19 @@ export const options = [ value: '3', }, ] + +export const fieldNamesOptions = [ + { + labelT: '选项一', + valueT: '1', + }, + { + labelT: '选项二', + valueT: '2', + }, + { + labelT: '选项三', + valueT: '3', + disabledT: true, + }, +] diff --git a/src/components/selector/index.en.md b/src/components/selector/index.en.md index a2d27b57c1..eb35bb268c 100644 --- a/src/components/selector/index.en.md +++ b/src/components/selector/index.en.md @@ -21,6 +21,7 @@ Provides multiple options for the user to choose from, typically used in filters | columns | Number of the displayed columns (Note that `grid` layout not support in IOS 9) | `number` | - | | defaultValue | Selected value by default | `SelectorValue[]` | `[]` | | disabled | Whether to disable selecting | `boolean` | `false` | +| fieldNames | Custom field name for label and value and disabled | `{ label: string, value: string, disabled: string }` | `{ label: 'label', value: 'value',disabled:'disabled' }` | | multiple | Whether to allow multiple selections | `boolean` | `false` | | onChange | Triggered when the value is changed | `(value: SelectorValue[], extend: { items: SelectorOption[] }) => void` | - | | options | Optional selector | `SelectorOption[]` | - | diff --git a/src/components/selector/index.zh.md b/src/components/selector/index.zh.md index bc1fb1e721..cd78e34eec 100644 --- a/src/components/selector/index.zh.md +++ b/src/components/selector/index.zh.md @@ -21,6 +21,7 @@ | columns | 列数(注意 `grid` 布局在 IOS 9 下不支持) | `number` | - | | defaultValue | 默认项 | `SelectorValue[]` | `[]` | | disabled | 是否全局禁止选中 | `boolean` | `false` | +| fieldNames | 自定义 options 中 label value disabled 的字段 | `{ label: string, value: string, disabled: string }` | `{ label: 'label', value: 'value',disabled:'disabled' }` | | multiple | 是否允许多选 | `boolean` | `false` | | onChange | 选项改变时触发 | `(value: SelectorValue[], extend: { items: SelectorOption[] }) => void` | - | | options | 可选项 | `SelectorOption[]` | - | diff --git a/src/components/selector/selector.tsx b/src/components/selector/selector.tsx index 74aca896c6..34b8740199 100644 --- a/src/components/selector/selector.tsx +++ b/src/components/selector/selector.tsx @@ -8,17 +8,19 @@ import Grid, { GridProps } from '../grid' import { usePropsValue } from '../../utils/use-props-value' import { CheckMark } from './check-mark' import { useConfig } from '../config-provider' +import { useFieldNames } from '../../hooks' +import type { FieldNamesType, BaseOptionType } from '../../hooks' const classPrefix = `adm-selector` type SelectorValue = string | number -export interface SelectorOption { - label: ReactNode +export type SelectorOption = { + label?: ReactNode description?: ReactNode - value: V + value?: V disabled?: boolean -} +} & BaseOptionType export type SelectorProps = { options: SelectorOption[] @@ -29,6 +31,7 @@ export type SelectorProps = { value?: V[] onChange?: (v: V[], extend: { items: SelectorOption[] }) => void showCheckMark?: boolean + fieldNames?: FieldNamesType } & NativeProps< | '--color' | '--checked-color' @@ -51,23 +54,25 @@ const defaultProps = { export const Selector = (p: SelectorProps) => { const props = mergeProps(defaultProps, p) + const [labelName, valueName, , disabledName] = useFieldNames(props.fieldNames) const [value, setValue] = usePropsValue({ value: props.value, defaultValue: props.defaultValue, onChange: val => { const extend = { get items() { - return props.options.filter(option => val.includes(option.value)) + return props.options.filter(option => val.includes(option[valueName])) }, } props.onChange?.(val, extend) }, }) + const { locale } = useConfig() const items = props.options.map(option => { - const active = (value || []).includes(option.value) - const disabled = option.disabled || props.disabled + const active = (value || []).includes(option[valueName]) + const disabled = option[disabledName] || props.disabled const itemCls = classNames(`${classPrefix}-item`, { [`${classPrefix}-item-active`]: active && !props.multiple, [`${classPrefix}-item-multiple-active`]: active && props.multiple, @@ -76,7 +81,7 @@ export const Selector = (p: SelectorProps) => { return (
{ if (disabled) { @@ -84,11 +89,11 @@ export const Selector = (p: SelectorProps) => { } if (props.multiple) { const val = active - ? value.filter(v => v !== option.value) - : [...value, option.value] + ? value.filter(v => v !== option[valueName]) + : [...value, option[valueName]] setValue(val) } else { - const val = active ? [] : [option.value] + const val = active ? [] : [option[valueName]] setValue(val) } }} @@ -97,7 +102,7 @@ export const Selector = (p: SelectorProps) => { (active && !props.multiple) || (active && props.multiple) } > - {option.label} + {option[labelName]} {option.description && (
{option.description} @@ -119,8 +124,11 @@ export const Selector = (p: SelectorProps) => { role='listbox' aria-label={locale.Selector.name} > - {!props.columns && {items}} - {props.columns && {items}} + {props.columns ? ( + {items} + ) : ( + {items} + )}
) } diff --git a/src/components/selector/tests/selector.test.tsx b/src/components/selector/tests/selector.test.tsx index 2eb12bf1df..66373a7d8a 100644 --- a/src/components/selector/tests/selector.test.tsx +++ b/src/components/selector/tests/selector.test.tsx @@ -1,7 +1,7 @@ import React from 'react' import { render, testA11y, fireEvent, screen } from 'testing' import Selector from '..' -import { options } from '../demos/options' +import { options, fieldNamesOptions } from '../demos/options' const classPrefix = `adm-selector` @@ -9,7 +9,18 @@ describe('Selector', () => { test('a11y', async () => { await testA11y() }) - + test('a11y fieldNames', async () => { + await testA11y( + + ) + }) test('onChange should be work', () => { const onChange = jest.fn() render() @@ -20,7 +31,31 @@ describe('Selector', () => { expect(onChange.mock.calls[0][0]).toMatchObject([options[1].value]) expect(onChange.mock.calls[0][1].items).toMatchObject([options[1]]) }) + test('fieldNames onChange should be work', () => { + const onChange = jest.fn() + render( + + ) + const label = screen.getByText(fieldNamesOptions[1].labelT) + fireEvent.click(label) + + expect(label).toHaveClass(`${classPrefix}-item-active`) + expect(onChange.mock.calls[0][0]).toMatchObject([ + fieldNamesOptions[1].valueT, + ]) + expect(onChange.mock.calls[0][1].items).toMatchObject([ + fieldNamesOptions[1], + ]) + }) test('disabled should be work', () => { const onChange = jest.fn() render( diff --git a/src/hooks/index.tsx b/src/hooks/index.tsx index 2218b2734a..c5d141ebd0 100644 --- a/src/hooks/index.tsx +++ b/src/hooks/index.tsx @@ -1,2 +1,6 @@ export { useFieldNames } from './useFieldNames' export type { FieldNamesType } from './useFieldNames' + +export type BaseOptionType = { + [key: string]: any +}