oxfordizeArray.tsx 1.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364
  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. export const oxfordizeElements = (elements: JSX.Element[]): JSX.Element => {
  13. if (elements.length === 0) {
  14. return <span />;
  15. }
  16. if (elements.length === 1) {
  17. return elements[0];
  18. }
  19. if (elements.length === 2) {
  20. return (
  21. <span>
  22. {elements[0]} and {elements[1]}
  23. </span>
  24. );
  25. }
  26. const joinedElements: JSX.Element[] = [];
  27. for (const [i, element] of elements.slice(0, -1).entries()) {
  28. joinedElements.push(<Fragment key={i}>{element}, </Fragment>);
  29. }
  30. joinedElements.push(
  31. <Fragment key={elements.length - 1}>and {elements[elements.length - 1]}</Fragment>
  32. );
  33. return <span>{joinedElements}</span>;
  34. };
  35. type Props = {
  36. children: React.ReactNode;
  37. };
  38. export function Oxfordize({children}: Props) {
  39. const elements = Children.toArray(children);
  40. if (elements.length === 1) {
  41. return <span>{elements[0]}</span>;
  42. }
  43. if (elements.length === 2) {
  44. return (
  45. <span>
  46. {elements[0]} and {elements[1]}
  47. </span>
  48. );
  49. }
  50. const joinedElements: JSX.Element[] = [];
  51. for (const [i, element] of elements.slice(0, -1).entries()) {
  52. joinedElements.push(<Fragment key={i}>{element}, </Fragment>);
  53. }
  54. joinedElements.push(
  55. <Fragment key={elements.length - 1}>and {elements[elements.length - 1]}</Fragment>
  56. );
  57. return <span>{joinedElements}</span>;
  58. }
  59. export default oxfordizeArray;