oxfordizeArray.tsx 1.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940
  1. import {Children, Fragment} from 'react';
  2. // Given a list of strings (probably nouns), join them into a single string
  3. // with correct punctuation and 'and' placement
  4. //
  5. // for example: ['A'] --> 'A'
  6. // ['A', 'B'] --> 'A and B'
  7. // ['A', 'B', 'C'] --> 'A, B, and C'
  8. const oxfordizeArray = (strings: string[]) =>
  9. strings.length <= 2
  10. ? strings.join(' and ')
  11. : [strings.slice(0, -1).join(', '), strings.slice(-1)[0]].join(', and ');
  12. type Props = {
  13. children: React.ReactNode;
  14. };
  15. export function Oxfordize({children}: Props) {
  16. const elements = Children.toArray(children);
  17. if (elements.length === 1) {
  18. return <span>{elements[0]}</span>;
  19. }
  20. if (elements.length === 2) {
  21. return (
  22. <span>
  23. {elements[0]} and {elements[1]}
  24. </span>
  25. );
  26. }
  27. const joinedElements: JSX.Element[] = [];
  28. for (const [i, element] of elements.slice(0, -1).entries()) {
  29. joinedElements.push(<Fragment key={i}>{element}, </Fragment>);
  30. }
  31. joinedElements.push(
  32. <Fragment key={elements.length - 1}>and {elements[elements.length - 1]}</Fragment>
  33. );
  34. return <span>{joinedElements}</span>;
  35. }
  36. export default oxfordizeArray;