section.tsx 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. import {Fragment, useMemo} from 'react';
  2. import type {AriaListBoxSectionProps} from '@react-aria/listbox';
  3. import {useListBoxSection} from '@react-aria/listbox';
  4. import {useSeparator} from '@react-aria/separator';
  5. import type {ListState} from '@react-stately/list';
  6. import type {Node} from '@react-types/shared';
  7. import type {FormSize} from 'sentry/utils/theme';
  8. import {
  9. SectionGroup,
  10. SectionHeader,
  11. SectionSeparator,
  12. SectionTitle,
  13. SectionWrap,
  14. } from '../styles';
  15. import type {SelectKey, SelectSection} from '../types';
  16. import {SectionToggle} from '../utils';
  17. import {ListBoxOption} from './option';
  18. interface ListBoxSectionProps extends AriaListBoxSectionProps {
  19. hiddenOptions: Set<SelectKey>;
  20. item: Node<any>;
  21. listState: ListState<any>;
  22. size: FormSize;
  23. onToggle?: (section: SelectSection<SelectKey>, type: 'select' | 'unselect') => void;
  24. }
  25. /**
  26. * A <li /> element that functions as a list box section (renders a nested <ul />
  27. * inside). https://react-spectrum.adobe.com/react-aria/useListBox.html
  28. */
  29. export function ListBoxSection({
  30. item,
  31. listState,
  32. onToggle,
  33. size,
  34. hiddenOptions,
  35. }: ListBoxSectionProps) {
  36. const {itemProps, headingProps, groupProps} = useListBoxSection({
  37. heading: item.rendered,
  38. 'aria-label': item['aria-label'],
  39. });
  40. const {separatorProps} = useSeparator({elementType: 'li'});
  41. const showToggleAllButton =
  42. listState.selectionManager.selectionMode === 'multiple' &&
  43. item.value.showToggleAllButton;
  44. const childItems = useMemo(
  45. () => [...item.childNodes].filter(child => !hiddenOptions.has(child.props.value)),
  46. [item.childNodes, hiddenOptions]
  47. );
  48. return (
  49. <Fragment>
  50. <SectionSeparator {...separatorProps} />
  51. <SectionWrap {...itemProps}>
  52. {(item.rendered || showToggleAllButton) && (
  53. <SectionHeader>
  54. {item.rendered && (
  55. <SectionTitle {...headingProps}>{item.rendered}</SectionTitle>
  56. )}
  57. {showToggleAllButton && (
  58. <SectionToggle item={item} listState={listState} onToggle={onToggle} />
  59. )}
  60. </SectionHeader>
  61. )}
  62. <SectionGroup {...groupProps}>
  63. {childItems.map(child => (
  64. <ListBoxOption
  65. key={child.key}
  66. item={child}
  67. listState={listState}
  68. size={size}
  69. />
  70. ))}
  71. </SectionGroup>
  72. </SectionWrap>
  73. </Fragment>
  74. );
  75. }