diff --git a/libs/util/array.spec.ts b/libs/util/array.spec.tsx
similarity index 57%
rename from libs/util/array.spec.ts
rename to libs/util/array.spec.tsx
index 10ff1373f4..d948eccf54 100644
--- a/libs/util/array.spec.ts
+++ b/libs/util/array.spec.tsx
@@ -5,6 +5,7 @@
*
* Copyright Oxide Computer Company
*/
+import { type ReactElement } from 'react'
import { expect, test } from 'vitest'
import { groupBy, intersperse, lowestBy, sortBy, sumBy } from './array'
@@ -68,12 +69,31 @@ test('sumBy', () => {
})
test('intersperse', () => {
- expect(intersperse([], 'x')).toEqual([])
- expect(intersperse(['a'], 'x')).toEqual(['a'])
+ expect(intersperse([], <>,>)).toEqual([])
- expect(intersperse(['a', 'b'], ',')).toEqual(['a', ',', 'b'])
- expect(intersperse(['a', 'b'], ',', 'or')).toEqual(['a', 'or', 'b'])
+ const a = a
+ const b = b
+ const c = c
+ const comma = <>,>
+ const or = <>or>
- expect(intersperse(['a', 'b', 'c'], ',')).toEqual(['a', ',', 'b', ',', 'c'])
- expect(intersperse(['a', 'b', 'c'], ',', 'or')).toEqual(['a', ',', 'b', ',', 'or', 'c'])
+ const getText = (el: ReactElement) => el.props.children
+ const getKey = (el: ReactElement) => el.key
+
+ expect(intersperse([a], comma).map(getText)).toEqual(['a'])
+ expect(intersperse([a], comma).map(getKey)).toEqual(['a'])
+
+ expect(intersperse([a, b], comma).map(getText)).toEqual(['a', ',', 'b'])
+ expect(intersperse([a, b], comma).map(getKey)).toEqual(['a', 'sep-1', 'b'])
+
+ expect(intersperse([a, b], comma, or).map(getText)).toEqual(['a', 'or', 'b'])
+ expect(intersperse([a, b], comma, or).map(getKey)).toEqual(['a', 'conj', 'b'])
+
+ let result = intersperse([a, b, c], comma)
+ expect(result.map(getText)).toEqual(['a', ',', 'b', ',', 'c'])
+ expect(result.map(getKey)).toEqual(['a', 'sep-1', 'b', 'sep-2', 'c'])
+
+ result = intersperse([a, b, c], comma, or)
+ expect(result.map(getText)).toEqual(['a', ',', 'b', ',', 'or', 'c'])
+ expect(result.map(getKey)).toEqual(['a', 'sep-1', 'b', 'sep-2', 'conj', 'c'])
})
diff --git a/libs/util/array.ts b/libs/util/array.ts
index fe3b996378..ab5ff348b4 100644
--- a/libs/util/array.ts
+++ b/libs/util/array.ts
@@ -6,6 +6,8 @@
* Copyright Oxide Computer Company
*/
+import { cloneElement, type ReactElement } from 'react'
+
/* eslint-disable @typescript-eslint/no-explicit-any */
const identity = (x: any) => x
@@ -80,12 +82,23 @@ export function sumBy(items: T[], fn: (item: T) => number): number {
/**
* If a conjunction is included, use that instead of `sep` when there are two items.
*/
-export function intersperse(items: T[], sep: T, conj?: T): T[] {
+export function intersperse(
+ items: ReactElement[],
+ sep: ReactElement,
+ conj?: ReactElement
+): ReactElement[] {
if (items.length <= 1) return items
- if (conj && items.length === 2) return [items[0], conj, items[1]]
+ if (conj && items.length === 2) {
+ const conj0 = cloneElement(conj, { key: `conj` })
+ return [items[0], conj0, items[1]]
+ }
return items.flatMap((item, i) => {
if (i === 0) return [item]
- if (conj && i === items.length - 1) return [sep, conj, item]
- return [sep, item]
+ const sep0 = cloneElement(sep, { key: `sep-${i}` })
+ if (conj && i === items.length - 1) {
+ const conj0 = cloneElement(conj, { key: `conj` })
+ return [sep0, conj0, item]
+ }
+ return [sep0, item]
})
}