1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192 |
- import React from 'react';
- import warning from '@douyinfe/semi-foundation/utils/warning';
- import { OptionProps } from './option';
- import { OptionGroupProps } from './optionGroup';
- const generateOption = (child: React.ReactElement, parent: any, index: number, newKey?: string | number): OptionProps => {
- const childProps = child.props;
- if (!child || !childProps) {
- return null;
- }
- const option = {
- value: childProps.value,
- // Dropdown menu rendering priority label value, children, value in turn downgrade
- label: childProps.label || childProps.children || childProps.value,
- _show: true,
- _selected: false,
- _scrollIndex: index,
- ...childProps,
- _parentGroup: parent,
- };
- // Props are collected from ReactNode, after React.Children.toArray
- // no need to determine whether the key exists in child
- // Even if the user does not explicitly declare it, React will always generate a key.
- option._keyInJsx = newKey || child.key;
-
- return option;
- };
- const getOptionsFromGroup = (selectChildren: React.ReactNode) => {
- let optionGroups: OptionGroupProps[] = [];
- let options: OptionProps[] = [];
- const emptyGroup: {
- label: string;
- children: OptionProps[];
- _show: boolean
- } = { label: '', children: [], _show: false };
- // avoid null
- let childNodes = React.Children.toArray(selectChildren) as React.ReactElement[];
- childNodes = childNodes.filter((childNode) => childNode && childNode.props);
- let type = '';
- let optionIndex = -1;
- childNodes.forEach((child: React.ReactElement<any, any>) => {
- if (child.type.isSelectOption) {
- type = 'option';
- optionIndex++;
- const option = generateOption(child, undefined, optionIndex);
- emptyGroup.children.push(option);
- options.push(option);
- } else if (child.type.isSelectOptionGroup) {
- type = 'group';
- // Avoid saving children (reactNode) by... removing other props from the group except children, causing performance problems
- let { children, ...restGroupProps } = child.props;
- restGroupProps.key = child.key;
- let originKeys = [];
- if (Array.isArray(children)) {
- // if group has children > 1
- originKeys = children.map(item => item.key);
- } else {
- originKeys.push(children.key);
- }
- children = React.Children.toArray(children);
- const childrenOption = children.map((option: React.ReactElement, index: number) => {
- let newKey = option.key;
- if (originKeys[index] === null) {
- newKey = child.key + '' + option.key; // if option in group and didn't set key, concat parent key to avoid conflict (default generate key just like .0, .1)
- }
- optionIndex++;
- return generateOption(option, restGroupProps, optionIndex, newKey);
- });
- const group = {
- ...child.props,
- children: childrenOption,
- key: child.key,
- };
- optionGroups.push(group);
- options = options.concat(childrenOption);
- } else {
- warning(true, '[Semi Select] The children of `Select` should be `Select.Option` or `Select.OptionGroup`');
- }
- });
- if (type === 'option') {
- optionGroups = [emptyGroup] as OptionGroupProps[];
- }
- return { optionGroups, options };
- };
- export { generateOption, getOptionsFromGroup };
|