utils.tsx 2.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
  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): 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. ...childProps,
  17. _parentGroup: parent,
  18. };
  19. return option;
  20. };
  21. const getOptionsFromGroup = (selectChildren: React.ReactNode) => {
  22. let optionGroups: OptionGroupProps[] = [];
  23. let options: OptionProps[] = [];
  24. const emptyGroup: {
  25. label: string;
  26. children: OptionProps[];
  27. _show: boolean;
  28. } = { label: '', children: [], _show: false };
  29. // avoid null
  30. // eslint-disable-next-line max-len
  31. const childNodes = React.Children.toArray(selectChildren).filter((childNode: React.ReactElement) => childNode && childNode.props);
  32. let type = '';
  33. childNodes.forEach((child: React.ReactElement<any, any>) => {
  34. if (child.type.isSelectOption) {
  35. type = 'option';
  36. const option = generateOption(child);
  37. emptyGroup.children.push(option);
  38. options.push(option);
  39. } else if (child.type.isSelectOptionGroup) {
  40. type = 'group';
  41. // Avoid saving children (reactNode) by... removing other props from the group except children, causing performance problems
  42. // eslint-disable-next-line prefer-const
  43. let { children, ...restGroupProps } = child.props;
  44. children = React.Children.toArray(children);
  45. const childrenOption = children.map((option: React.ReactElement) => generateOption(option, restGroupProps));
  46. const group = {
  47. ...child.props,
  48. children: childrenOption,
  49. key: child.key,
  50. };
  51. optionGroups.push(group);
  52. options = options.concat(childrenOption);
  53. } else {
  54. warning(true, '[Semi Select] The children of `Select` should be `Select.Option` or `Select.OptionGroup`');
  55. }
  56. });
  57. if (type === 'option') {
  58. optionGroups = [emptyGroup];
  59. }
  60. return { optionGroups, options };
  61. };
  62. export { generateOption, getOptionsFromGroup };