roleSelectControl.tsx 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. import React from 'react';
  2. import {components, OptionProps} from 'react-select';
  3. import styled from '@emotion/styled';
  4. import SelectControl, {ControlProps} from 'app/components/forms/selectControl';
  5. import space from 'app/styles/space';
  6. import {MemberRole} from 'app/types';
  7. import theme from 'app/utils/theme';
  8. type OptionType = {
  9. label: string;
  10. value: string;
  11. disabled: boolean;
  12. description: string;
  13. };
  14. type Props = Omit<ControlProps<OptionType>, 'onChange' | 'value'> & {
  15. roles: MemberRole[];
  16. disableUnallowed: boolean;
  17. value?: string;
  18. /**
  19. * Narrower type than SelectControl because there is no empty value
  20. */
  21. onChange?: (value: OptionType) => void;
  22. };
  23. function RoleSelectControl({roles, disableUnallowed, ...props}: Props) {
  24. return (
  25. <SelectControl
  26. options={roles?.map(
  27. (r: MemberRole) =>
  28. ({
  29. value: r.id,
  30. label: r.name,
  31. disabled: disableUnallowed && !r.allowed,
  32. description: r.desc,
  33. } as OptionType)
  34. )}
  35. components={{
  36. Option: ({label, data, ...optionProps}: OptionProps<OptionType>) => (
  37. <components.Option label={label} {...(optionProps as any)}>
  38. <RoleItem>
  39. <h1>{label}</h1>
  40. <div>{data.description}</div>
  41. </RoleItem>
  42. </components.Option>
  43. ),
  44. }}
  45. styles={{
  46. control: provided => ({
  47. ...provided,
  48. borderBottomLeftRadius: theme.borderRadius,
  49. borderBottomRightRadius: theme.borderRadius,
  50. }),
  51. menu: provided => ({
  52. ...provided,
  53. borderRadius: theme.borderRadius,
  54. marginTop: space(0.5),
  55. width: '350px',
  56. overflow: 'hidden',
  57. }),
  58. }}
  59. {...props}
  60. />
  61. );
  62. }
  63. const RoleItem = styled('div')`
  64. display: grid;
  65. grid-template-columns: 80px 1fr;
  66. grid-gap: ${space(1)};
  67. h1,
  68. div {
  69. font-size: ${p => p.theme.fontSizeSmall};
  70. line-height: 1.4;
  71. margin: ${space(0.25)} 0;
  72. }
  73. `;
  74. export default RoleSelectControl;