import React, { useState, useRef, useEffect } from 'react'; import './select.scss'; import { Input, Select, Button, Icon, Avatar, Checkbox, Form, withField, Space, Tag, Switch } from '../../index'; import CustomTrigger from './CustomTrigger'; import classNames from 'classnames'; const Option = Select.Option; import { IconSearch, IconGift } from '@douyinfe/semi-icons'; export default { title: 'Select', parameters: { chromatic: { disableSnapshot: true }, }, } let Test = () => { let [options, setOptions] = useState([1, 2, 3, 4]); function add() { let newOptions = Array.from( { length: Math.floor(Math.random() * 10), }, (v, i) => i + 1 ); setOptions(newOptions); } let style = { width: 150, margin: 20, }; let slotStyle = { backgroundColor: 'whitesmoke', height: '40px', display: 'flex', justifyContent: 'center', alignItems: 'center', borderRadius: '0 0 6px 6px', }; let outSlotStyle = { backgroundColor: 'whitesmoke', height: '29px', display: 'flex', justifyContent: 'center', alignItems: 'center', cursor: 'pointer', }; const click = e => {}; let outSlotNode = (
click(e)}> sendLarkNotification
); return ( <> ); }; const AutoFocusDemo = () => { return ( <>
test-div
); }; export const AutoFocus = () => ; AutoFocus.story = { name: 'autoFocus', }; export const InnerBottomSlotOuterBottomSlot = () => ; InnerBottomSlotOuterBottomSlot.story = { name: 'innerBottomSlot / outerBottomSlot', }; export const InnerTopSlotOuterTopSlot = () => { const slot =
未找到应用?
; return (
innerTopSlot
outerTopSlot
); }; InnerTopSlotOuterTopSlot.story = { name: 'innerTopSlot / outerTopSlot', }; export const OneOptionJsxWithOtherOptionArray = () => ( ); OneOptionJsxWithOtherOptionArray.story = { name: 'one option jsx with other option array', }; let options = [ { value: 'all', label: '全部', otherKey: 'all semi', }, { value: 'abc', label: '抖音', otherKey: 'abc semi', }, { value: 'hotsoon', label: '火山小视频', otherKey: 'hostsoom semi', }, { value: 'pipixia', label: '皮皮虾', otherKey: 'pif', }, { value: 'toutiao', label: '今日头条', otherKey: 'toutiao semi', }, { value: 'rd', label: 'rd', otherKey: 'semi rd', }, { value: 'ued', label: 'ued', otherKey: 'semi ued', }, { value: 'ued', label: 'japan', otherKey: 'semi ued', }, { value: '+86', label: '+86', otherKey: 'semi', }, ]; let longOptions = options.concat({ value: 'long', label: 'Semi Design 是一个设计系统,它定义了一套中后台设计与前端基础组', }); export const SelectSize = () => (

使用方不设width时,下拉菜单根据内容自动适配宽度(不推荐这样使用,select的宽度会动态变化)

{/* */}

通过style设width的

90px:{' '} 120px:{' '} 400px:{' '}
100%:{' '}

通过css设width的


dropdownMatchSelectWidth

当该项设为true时,下拉菜单最小宽度会等于Select宽度(默认为true)

style方式指定90px:

需要强制下拉菜单与select同宽的时候

通过dropdownStyle覆盖min-width,将其设成与select的width同样的值

} suffix={} >

insetLabel

showClear

showArrow = false

defaultValue是不存在的值

); WithPrefixSuffixInsetLabelShowClearShowArrow.story = { name: 'with prefix / suffix / insetLabel, showClear, showArrow', }; WithPrefixSuffixInsetLabelShowClearShowArrow.parameters = { chromatic: { disableSnapshot: false }, }; export const WithDefaultSelected = () => ( ); WithDefaultSelected.story = { name: 'with default selected', }; export const WithScrollbar = () => ( ); WithScrollbar.story = { name: 'with scrollbar', }; class Link extends React.Component { get provinces() { return ['Sichuan', 'Guangdong']; } get maps() { return { Sichuan: ['Chengdu', 'Dujiangyan'], Guangdong: ['Guangzhou', 'Shenzhen', 'Dongguan'], }; } constructor() { super(); this.state = { provinces: this.provinces, maps: this.maps, citys: this.maps[this.provinces[0]], city: this.maps[this.provinces[0]][0], }; this.provinceChange = this.provinceChange.bind(this); this.cityChange = this.cityChange.bind(this); } provinceChange(newProvince) { const { maps } = this.state; this.setState({ citys: maps[newProvince], city: maps[newProvince][0], }); } cityChange(city) { this.setState({ city, }); } render() { const { provinces, citys, city } = this.state; return ( ); } } export const TwoSelectChangeAtTheSameTime = () => ; TwoSelectChangeAtTheSameTime.story = { name: 'two select change at the same time', }; export const SelectMultiple = () => ( <>





maxTagCount = 3


maxTagCount = 3, showRestTagsPopover


maxTagCount = 3, max=5
); SelectMultiple.story = { name: 'select multiple', }; SelectMultiple.parameters = { chromatic: { disableSnapshot: false }, }; export const SelectDisabled = () => ( ); SelectDisabled.story = { name: 'select disabled', }; function filter(input, option) { console.log(option); return option.label.includes(input); } const spanStyle = { display: 'inline-block', marginRight: '8px', width: '16px', height: '16px', borderRadius: '50%', border: '1px solid var(--semi-color-bg-1)', }; const colorOptions = [ { value: 'grey-1', spanStyle: { ...spanStyle, backgroundColor: 'rgb(107, 116, 117)' }, }, { value: 'purple-5', spanStyle: { ...spanStyle, backgroundColor: 'rgb(158, 40, 179)' }, }, { value: 'pink-2', spanStyle: { ...spanStyle, backgroundColor: 'rgb(233, 30, 99)' }, }, { value: 'blue-3', spanStyle: { ...spanStyle, backgroundColor: 'rgb(0, 119, 250)' }, }, ]; const alignStyle = { display: 'flex', alignItems: 'center', }; const customFilter = (input, option) => { return option.value.includes(input); }; export const SelectFilterSingle = () => (
默认筛选
自定义筛选函数
filter为true,但option label为node时
); SelectFilterSingle.story = { name: 'select filter single', }; export const SelectFilterMultiple = () => ( <> ); SelectFilterMultiple.story = { name: 'select filter multiple', }; const OptionLabelProp = () => { const [value, setValue] = useState(1); return ( <> 设置optionLabelProp属性(默认为'children')为'value'时,回填到选择框中的文本会是Option.value







多选 ); }; class CustomRender extends React.Component { constructor() { super(); this.state = { list: [ { name: '夏可漫', email: 'xiakeman@example.com', abbr: 'XK', color: 'amber', }, { name: '申悦', email: 'shenyue@example.com', abbr: 'SY', color: 'indigo', }, { name: '曲晨一', email: 'quchenyi@example.com', abbr: 'CY', color: 'blue', }, { name: '文嘉茂', email: 'wenjiamao@example.com', abbr: 'JM', color: 'cyan', }, ], }; } renderCustomOption(item, index) { const optionStyle = { display: 'flex', }; return ( ); } renderSelectedItem(optionNode) { return (
{optionNode.abbr} {optionNode.email}
); } renderMultipleSelectedItem(optionNode) { let content = (
{optionNode.abbr}
); return { isRenderInTag: true, content, }; } renderMultipleWithoutTag(optionNode) { let content = (
{optionNode.abbr}
); return { isRenderInTag: false, content, }; } render() { const { list } = this.state; return ( ); } } export const RenderSelectedItem = () => ( <> renderSelectedItem

OptionLabelProp ); RenderSelectedItem.story = { name: 'renderSelectedItem', }; RenderSelectedItem.parameters = { chromatic: { disableSnapshot: false }, }; const ControlledSelect = () => { const [value, setValue] = useState('nick'); const [value2, setValue2] = useState('jerry'); const [value3, setValue3] = useState(); const [value4, setValue4] = useState(['nick']); const [value5, setValue5] = useState(); return ( <> value + onChange

只传value,不传onChange

value + onChange , 多选

value, 多选
filter为true,但option label为node时
); }; export const Controlled = () => ; Controlled.story = { name: 'controlled', }; const UnControlledSelect = () => { const onChange = value => { console.log(value); }; return ( <>
defaultValue在list中不存在
defaultValue在list中存在
); }; export { UnControlledSelect }; UnControlledSelect.story = { name: '非受控组件' }; export const TestScroll = () => (
); TestScroll.story = { name: 'test scroll', }; let optionList = [ { value: 'tony', label: 'Ironman', }, { value: 'Thor', label: 'Thor', }, { value: 'steve', label: 'Caption', }, { value: 'peter', label: 'SpiderBoy', }, ]; export const OptionList = () => ( ); OptionList.story = { name: 'optionList', }; export const InsetLabel = () => ( <> ); InsetLabel.story = { name: 'insetLabel', }; export const ChangeOptionDynamic = () => { function App() { let [options, setOptions] = useState([]); let [index, setIndex] = useState(0); const addOption = () => { const randomItem = optionList[index]; index = index + 1; setIndex(index); options = [...options, { ...randomItem }]; setOptions(options); }; const reset = () => { setOptions([]); setIndex(0); }; return (

多选

); } return ; }; ChangeOptionDynamic.story = { name: 'change option dynamic', }; let list = [ { value: 'tony', label: 'Ironman', otherKey: { role: 1, }, }, { value: 'Thor', label: 'Thor', otherKey: { role: 2, }, }, { value: 'steve', label: 'Caption', otherKey: { role: 3, }, }, { value: 'peter', label: 'SpiderBoy', otherKey: { role: 4, }, }, ]; const SearchDemo1 = () => { const [optionList, setOptionList] = useState(list); const [loading, setLoading] = useState(false); const handleSearch = value => { setLoading(true); let length = Math.ceil(Math.random() * 10); let result = Array.from( { length, }, (v, i) => { return { value: value + i, label: value + i, otherKey: { role: i, }, }; } ); setTimeout(() => { setOptionList(result); setLoading(false); }, 1000); }; const [value, setValue] = useState(optionList[0].value); const onChange = value => { console.log(value); setValue(value); }; return (
受控: 非受控: 多选非受控
); }; import debounce from 'lodash/debounce'; class SearchDemo2 extends React.Component { constructor() { super(); this.state = { loading: false, optionList: [ { value: 'abc', label: '抖音', type: 1, }, { value: 'hotsoon', label: '火山小视频', type: 2, }, { value: 'pipixia', label: '皮皮虾', type: 3, }, { value: 'toutiao', label: '今日头条', type: 4, }, ], value: [], }; this.handleSearch = debounce(this.handleSearch, 800).bind(this); this.onChange = this.onChange.bind(this); this.customRender = this.customRender.bind(this); } handleSearch(inputValue) { this.setState({ loading: true, }); let length = Math.ceil(Math.random() * 100); let result = Array.from( { length, }, (v, i) => { return { value: inputValue + i, label: 'label' + i, type: i + 1, }; } ); setTimeout(() => { this.setState({ optionList: result, loading: false, }); }, 2000); } onChange(value) { this.setState({ value, }); console.log(value); } customRender(optionNode) { return optionNode.value + optionNode.label; } render() { const { loading, optionList, value } = this.state; return (


); } } export const Search = () => ( <> ); Search.story = { name: 'search', }; export const IncomeDetail = ({ config = {}, params = {} }) => { const [detailList, setDetailList] = useState([]); const [hasMore, setHasMore] = useState(true); const [loading, setLoading] = useState(); let lock; const fetchData = (outParams = {}) => { if (lock) { return; } setLoading(true); // 参数 // 请求 fetch({ url: URL.user_profit, method: 'get', baseURL: config.webcast_host, params, }) .then(res => { lock = false; setLoading(false); console.log('++++', data); }) .catch(() => { setLoading(false); Toast.show('网络异常,请稍后重试'); }); }; useEffect(fetchData, []); // 监听滚动设置吸顶 以及加载更多 useEffect(() => { window.addEventListener('scroll', function() { // 加载更多 const scrollY = window.scrollY; const scrollHeight = document.documentElement.scrollHeight; const screenHeight = screen.height; if (!loading && hasMore && scrollY + screenHeight + 300 > scrollHeight) { fetchData(); } }); }, [detailList.length]); return (
); }; export const AllowCreate = () => ( ); AllowCreate.story = { name: 'allowCreate', }; export const AllowCreateCustomRender = () => ( ); AllowCreateCustomRender.story = { name: 'allowCreate custom render', }; let AllowCreateControlledDemo = () => { let [value, setValue] = useState(); const optionList = [ { value: 'abc', label: '抖音', }, { value: 'hotsoon', label: '火山小视频', }, { value: 'pipixia', label: '皮皮虾', }, { value: 'toutiao', label: '今日头条', }, ]; const [list, setList] = useState(optionList); const handleSelect = v => { var lastOne = v[v.length - 1]; if (lastOne && list.findIndex(item => item.value === lastOne) == -1) { list.push({ value: lastOne, label: lastOne, }); } setList(list); setValue(v); }; return ( ); }; const AllowCreateDemo = () => { let [value, setValue] = useState(); const optionList = [ { value: 'abc', label: '抖音', }, { value: 'hotsoon', label: '火山小视频', }, { value: 'pipixia', label: '皮皮虾', }, { value: 'toutiao', label: '今日头条', }, ]; const [list, setList] = useState(optionList); const handleSelect = v => { var lastOne = v[v.length - 1]; if (lastOne && list.findIndex(item => item.value === lastOne) == -1) { list.push({ value: lastOne, label: lastOne, }); } setList(list); // setValue(v) }; return ( ); }; export const AllowCreateWithDefaultValue = () => ; AllowCreateWithDefaultValue.story = { name: 'allowCreate with defaultValue', }; class HideDemo extends React.Component { constructor(props) { super(props); this.state = { optionList: [ { value: 'abc', label: '抖音', }, { value: 'hotsoon', label: '火山小视频', }, { value: 'pipixia', label: '皮皮虾', }, { value: 'toutiao', label: '今日头条', }, ], selectedItems: [], }; this.onChange = this.onChange.bind(this); } onChange(selectedItems) { this.setState({ selectedItems, }); } render() { let { optionList, selectedItems } = this.state; let filterOptions = optionList.filter(option => !selectedItems.includes(option.value)); return ( ); } } export const AutoHiddenSelectedItem = () => ; AutoHiddenSelectedItem.story = { name: 'auto hidden selected item', }; class CustomCreate extends React.Component { constructor(props) { super(props); this.state = { optionList: [ { value: 'abc', label: '抖音', }, { value: 'hotsoon', label: '火山小视频', }, { value: 'pipixia', label: '皮皮虾', }, { value: 'toutiao', label: '今日头条', }, { value: 0, label: 0, }, ], selectedItems: ['fefe'], }; this.onChange = this.onChange.bind(this); this.customRender = this.customRender.bind(this); this.search = this.search.bind(this); } onChange(selectedItems) { console.log(selectedItems); // this.setState({ selectedItems, optionList: [] }); this.setState({ selectedItems, }); // this.setState({ optionList: [] }); } customRender(v) { return ( <> label:{v.label} value:{v.value} ); } customCreate(inputValue, isFocus) { let style = { padding: 12, cursor: 'pointer', backgroundColor: isFocus ? 'var(--semi-color-fill-0)' : '#FFF', }; return
{'create' + inputValue}
; } search(inputValue) { let length = Math.ceil(Math.random() * 10); let result = Array.from( { length, }, (v, i) => { return { value: inputValue + i, label: inputValue + i, type: i + 1, }; } ); console.log(result); // result = result.concat(selectedOption); this.setState({ optionList: result, }); } render() { let { optionList, selectedItems } = this.state; return ( <> ); } } export const _CustomCreate = () => ; _CustomCreate.story = { name: 'CustomCreate', }; class OptionGroupDemo extends React.Component { constructor(props) { super(props); this.handleSearch = this.handleSearch.bind(this); this.state = { groups: [ { label: 'Asia', children: [ { label: 'China', value: 'zhongguo', }, { label: 'Koera', value: 'hanguo', }, ], }, { label: 'Europe', children: [ { label: 'Germany', value: 'deguo', }, { label: 'France', value: 'faguo', }, ], }, { label: 'Other', children: [ { label: 'vf', value: 'Sourth', }, ], }, ], }; } handleSearch(input) { let groups = [1, 2, 3].map(i => { return { label: i, // label: Math.random(), children: [10, 20].map(j => { return { label: Math.random(), value: Math.random(), }; }), }; }); this.setState({ groups, }); } renderGroup(group, index) { const options = group.children.map(option => ( )); return {options}; } render() { const { groups } = this.state; return ( <> ); } } export const SelectOptionGroup = () => ; SelectOptionGroup.story = { name: 'Select OptionGroup', }; const BlurDemo = () => { const onBlur = (value, e) => { console.log(value); console.log(e); }; const onFocus = (value, e) => { console.log(value); console.log(e); }; return ( <> ); }; export const SelectOnBlurOnFocus = () => ; SelectOnBlurOnFocus.story = { name: 'Select onBlur/onFocus', }; const AutoAdjustOverflowDemo = () => { const [list, setList] = useState([ { value: 'abc', label: '1111', }, { value: 'hotsoon', label: '1112', }, { value: 'pipixia', label: '1113', }, { value: 'toutiao', label: '1114', }, ]); const onSearch = () => { let newList = Array.from( { length: Math.floor(Math.random() * 10), }, (v, i) => { return { value: i, label: i, }; } ); setList(newList); console.log(newList); }; return (
); }; export const FilterAllowCreate = () => ; FilterAllowCreate.story = { name: 'Filter + allowCreate', }; const SelectRefDemo = () => { const ref = useRef(); const secondRef = useRef(); const [open, setOpen] = useState(false); const list = [ { value: 'abc', label: 'Abc', }, { value: 'hotsoon', label: 'Hotsoon', }, { value: 'pipixia', label: 'Pipixia', }, { value: 'toutiao', label: 'TooBuzz', }, ]; const change = () => { if (!open) { ref.current.open(); setOpen(true); } else { ref.current.close(); setOpen(false); } }; const focus = () => { ref.current.focus(); }; const clearInput = () => { ref.current.clearInput(); }; const deselectAll = () => { ref.current.deselectAll(); }; const selectAll = () => { ref.current.selectAll(); }; return ( <>

onChangeWithObject = false

onChangeWithObject = true

); }; export const Ref = () => ; Ref.story = { name: 'ref', }; export const CustomTriggerDemo = () => ; CustomTriggerDemo.story = { name: 'custom trigger' } class VirtualizeClassDemo extends React.Component { constructor(props) { super(props); // this.handleSearch = this.handleSearch.bind(this); let newOptions = Array.from({ length: 1000 }, (v, i) => ({ label: `o-${i}`, value: `v-${v}-${i}` })); this.state = { optionList: newOptions, }; } render() { let { groups, optionList } = this.state; let virtualize = { height: 300, widht: '100%', itemSize: 36, }; return ( <> ); } } export const VirtualizeDemo = () => ; VirtualizeDemo.story = { name: 'virtualize select' } const SelectPosition = () => { return (

p

p

p

p

p

p

p

p

p

p

p

p

p

p

p

p

p

p

p

p

p

p

p

p

p

p

p

p

p

p

p

p

p

p

p

p

p

p

p

p

p

p

p

p

p

p

p

p

p

p

p

p

p

p

p

p

p

p

p

p

p

p

p

p

p

); }; export { SelectPosition }; SelectPosition.story = { name: 'Select position problem' } const RenderOptionDemo = () => { const renderOptionItem = renderProps => { const { disabled, selected, label, value, focused, className, style, onMouseEnter, onClick, empty, emptyContent, ...rest } = renderProps; const optionCls = classNames({ ['custom-option-render']: true, ['custom-option-render-focused']: focused, ['custom-option-render-disabled']: disabled, ['custom-option-render-selected']: selected, }); // Notice: // 1.props传入的style需在wrapper dom上进行消费,否则在虚拟化场景下会无法正常使用 // 2.选中(selected)、聚焦(focused)、禁用(disabled)等状态的样式需自行加上,你可以从props中获取到相对的boolean值 // 3.onMouseEnter需在wrapper dom上绑定,否则上下键盘操作时显示会有问题 return (
onClick()} onMouseEnter={e => onMouseEnter()} >
{label}
); }; return ( <> ); }; export const RenderOptionItem = () => ; RenderOptionItem.story = { name: 'renderOptionItem', }; const FilterDefaultOpen = () => { const [value1, setValue1] = useState('a-1'); return ( <> ); }; export { FilterDefaultOpen }; FilterDefaultOpen.story = { name: 'Filter + defaultOpen' }; const CustomSelect = props => { const { fieldRef, ...rest } = props; return option.label + 1} > ); }; export const Value0 = () => ; Value0.story = { name: 'value=0', }; export const ScrollIntoView = () => (

single selection

single selection with no selected item

The selected node is the last

The selected node is the first

multiple selection

multiple selection with no selected item

); ScrollIntoView.story = { name: 'scroll into view', }; export const SelectInputPropsDemo = () => { const inputProps = { className: 'ttt', onCompositionEnd: (v) => console.log(v.target.value) }; return ( ) }; SelectInputPropsDemo.story = { name: 'inputProps', }; export const AutoClearSearchValue = () => { const [val, setVal] = useState(['semi1']); const [clear, setClear] = useState(false); const optionList = [ { label: 'semi1', value: 'semi1' }, { label: 'semi2', value: 'semi2' }, { label: 'semi3', value: 'semi3' }, { label: 'semi4', value: 'semi4' }, { label: 'semi5', value: 'semi5' }, { label: 'semi6', value: 'semi6' }, ]; const [loading, setLoading] = useState(false); const [list, setList] = useState(optionList); const [value, setValue] = useState(''); const handleChange = newValue => { setValue(newValue); }; const data2 = [ { label: "Design", value: '123456', } ] const handleSearch = (inputValue) => { setLoading(true); if (inputValue) { setTimeout(() => { setLoading(false); setList(data2); }, 1000); } else { setList(optionList) setLoading(false); } }; return ( <>

autoClearSearchValue

setClear(checked)}>

Controlled mode + multiple



Uncontrolled mode + multiple

Uncontrolled mode + multiple + defaultValue

controlled mode + update optionList + remote + autoClearSearchValue = false

) } AutoClearSearchValue.story = { name: 'AutoClearSearchValue', }; export const RenderSelectedItemCallCount = () => { const list = [ { "name": "夏可漫", "email": "xiakeman@example.com", "avatar": "https://sf6-cdn-tos.douyinstatic.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/avatarDemo.jpeg" }, { "name": "申悦", "email": "shenyue@example.com", "avatar": "https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/bag.jpeg" }, { "name": "曲晨一", "email": "quchenyi@example.com", "avatar": "https://sf6-cdn-tos.douyinstatic.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/8bd8224511db085ed74fea37205aede5.jpg" }, { "name": "文嘉茂", "email": "wenjiamao@example.com", "avatar": "https://sf6-cdn-tos.douyinstatic.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/6fbafc2d-e3e6-4cff-a1e2-17709c680624.png" }, { "name": "文嘉茂2", "email": "wenjiamao@example.com", "avatar": "https://sf6-cdn-tos.douyinstatic.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/6fbafc2d-e3e6-4cff-a1e2-17709c680624.png" }, { "name": "文嘉茂3", "email": "wenjiamao@example.com", "avatar": "https://sf6-cdn-tos.douyinstatic.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/6fbafc2d-e3e6-4cff-a1e2-17709c680624.png" }, ] const renderMultipleWithCustomTag = (optionNode, { onClose }) => { console.count('rerender') const content = ( {optionNode.name} ); return { isRenderInTag: false, content }; } const renderCustomOption = (item, index) => { const optionStyle = { display: 'flex', paddingLeft: 24, paddingTop: 10, paddingBottom: 10 } return (
{item.name}
{item.email}
) } return ( <> ); } RenderSelectedItemCallCount.story = { name: 'RenderSelectedItemCallCount', }; const RenderSelectedItemWithMaxTagCount = () => { const list = [ { "name": "夏可漫", "email": "xiakeman@example.com", "avatar": "https://sf6-cdn-tos.douyinstatic.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/avatarDemo.jpeg" }, { "name": "申悦", "email": "shenyue@example.com", "avatar": "https://sf6-cdn-tos.douyinstatic.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/bf8647bffab13c38772c9ff94bf91a9d.jpg" }, { "name": "曲晨一", "email": "quchenyi@example.com", "avatar": "https://sf6-cdn-tos.douyinstatic.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/8bd8224511db085ed74fea37205aede5.jpg" }, { "name": "文嘉茂", "email": "wenjiamao@example.com", "avatar": "https://sf6-cdn-tos.douyinstatic.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/6fbafc2d-e3e6-4cff-a1e2-17709c680624.png" }, ]; const renderMultipleWithCustomTag = (optionNode, { onClose }) => { const content = ( {optionNode.email} ); return { isRenderInTag: false, content }; }; const renderMultipleWithCustomTag2 = (optionNode, { onClose }) => { const content = ( {optionNode.name} ); return { isRenderInTag: false, content }; }; const renderCustomOption = (item, index) => { const optionStyle = { display: 'flex', paddingLeft: 24, paddingTop: 10, paddingBottom: 10 }; return (
{item.email}
{item.email}
); }; return ( <> renderSelectedItem + maxTagCount=10 + defaultValue.length=2


renderSelectedItem + maxTagCount=1 + defaultValue.length=2 + filter
); }; export const NPlusTruncationStrategy = () => { const shortVal = ['semi11', 'semi1'] const val = ['semi11', 'semi1', 'semi3', 'semi4', 'semi10'] const allSelect = ['semi11', 'semi1', 'semi2', 'semi3', 'semi4', 'semi5', 'semi6', 'semi7', 'semi8', 'semi9', 'semi10'] const options = [ { label: 'semi1semi1', value: 'semi1' }, { label: 'semi2semi2semi2', value: 'semi2' }, { label: 'semi3semi3semi3semi3', value: 'semi3' }, { label: 'semi4semi4semi4semi4semi4', value: 'semi4' }, { label: 'semi5semi5semi5semi5semi5semi5', value: 'semi5' }, { label: 'semi6semi6semi6semi6semi6semi6semi6', value: 'semi6' }, { label: 'semi7semi7semi7semi7semi7semi7semi7', value: 'semi7' }, { label: 'semi8semi8semi8semi8semi8semi8semi8', value: 'semi8' }, { label: 'semi9semi9semi9semi9semi9semi9semi9', value: 'semi9' }, { label: 'semi10semi10semi10semi10semi10semi10', value: 'semi10' }, { label: '我是中文超长选项我真的真的真的真的真的真的超级长', value: 'semi11' }, ]; // expandRestTagsOnClick return ( <>

未设置宽度 和 maxTagCount

defaultValue.length = 5




未设置宽度

maxTagCount = 2 + defaultValue.length = 5



maxTagCount = 2 + defaultValue.length = 5 + expandRestTagsOnClick=false



maxTagCount = 6 + defaultValue.length = 5



maxTagCount = 6 + defaultValue.length = 5 + filter




定宽

maxTagCount = 2 + defaultValue.length = 2



maxTagCount = 5 + defaultValue.length = 5



maxTagCount = 10 + defaultValue.length = 11



maxTagCount = 10 + defaultValue.length = 11 + filter



maxTagCount = 10 + defaultValue.length = 11 + expandRestTagsOnClick=false




能保证正常渲染的最小宽度至少是120px




前缀/后缀/insetLabel

maxTagCount = 2 + defaultValue.length = 2 + prefix



maxTagCount = 6 + defaultValue.length = 5 + suffix



maxTagCount = 6 + defaultValue.length = 11 + insetLabel




renderSelectedItem


) } NPlusTruncationStrategy.story = { name: 'NPlusTruncationStrategy', }; export const emptyContent = () => { const list = null; return (