utils.tsx 2.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. import React from 'react';
  2. import warning from '@douyinfe/semi-foundation/utils/warning';
  3. import { OptionProps } from './option';
  4. import { OptionGroupProps } from './optionGroup';
  5. const generateOption = (child: React.ReactElement, parent: any, index: number): OptionProps => {
  6. const childProps = child.props;
  7. if (!child || !childProps) {
  8. return null;
  9. }
  10. const option = {
  11. value: childProps.value,
  12. // Drop-down menu rendering priority label value, children, value in turn downgrade
  13. label: childProps.label || childProps.children || childProps.value,
  14. _show: true,
  15. _selected: false,
  16. _scrollIndex: index,
  17. ...childProps,
  18. _parentGroup: parent,
  19. };
  20. return option;
  21. };
  22. const getOptionsFromGroup = (selectChildren: React.ReactNode) => {
  23. let optionGroups: OptionGroupProps[] = [];
  24. let options: OptionProps[] = [];
  25. const emptyGroup: {
  26. label: string;
  27. children: OptionProps[];
  28. _show: boolean;
  29. } = { label: '', children: [], _show: false };
  30. // avoid null
  31. // eslint-disable-next-line max-len
  32. let childNodes = React.Children.toArray(selectChildren) as React.ReactElement[];
  33. childNodes = childNodes.filter((childNode) => childNode && childNode.props);
  34. let type = '';
  35. let optionIndex = -1;
  36. childNodes.forEach((child: React.ReactElement<any, any>) => {
  37. if (child.type.isSelectOption) {
  38. type = 'option';
  39. optionIndex++;
  40. const option = generateOption(child, undefined, optionIndex);
  41. emptyGroup.children.push(option);
  42. options.push(option);
  43. } else if (child.type.isSelectOptionGroup) {
  44. type = 'group';
  45. // Avoid saving children (reactNode) by... removing other props from the group except children, causing performance problems
  46. // eslint-disable-next-line prefer-const
  47. let { children, ...restGroupProps } = child.props;
  48. children = React.Children.toArray(children);
  49. const childrenOption = children.map((option: React.ReactElement) => {
  50. optionIndex++;
  51. return generateOption(option, restGroupProps, optionIndex);
  52. });
  53. const group = {
  54. ...child.props,
  55. children: childrenOption,
  56. key: child.key,
  57. };
  58. optionGroups.push(group);
  59. options = options.concat(childrenOption);
  60. } else {
  61. warning(true, '[Semi Select] The children of `Select` should be `Select.Option` or `Select.OptionGroup`');
  62. }
  63. });
  64. if (type === 'option') {
  65. optionGroups = [emptyGroup];
  66. }
  67. return { optionGroups, options };
  68. };
  69. export { generateOption, getOptionsFromGroup };