From 0db7f3be74aa3aa7a2015bc405a4f882afe89a68 Mon Sep 17 00:00:00 2001 From: David Wheatley Date: Mon, 8 Nov 2021 23:52:47 +0000 Subject: [PATCH] feat: allow use of any tag in `listItems` helper (#3147) * feat: allow use of any tag in `listItems` helper * fix: fix missing optional chaining * chore: use more optional chaining * fix: various typings errors * chore: replace `Vnode[]` with `Children` --- .../core/js/src/common/helpers/listItems.tsx | 48 ++++++++++++++----- 1 file changed, 35 insertions(+), 13 deletions(-) diff --git a/framework/core/js/src/common/helpers/listItems.tsx b/framework/core/js/src/common/helpers/listItems.tsx index 218b353c9..078f868bd 100644 --- a/framework/core/js/src/common/helpers/listItems.tsx +++ b/framework/core/js/src/common/helpers/listItems.tsx @@ -1,14 +1,15 @@ import type Mithril from 'mithril'; import Separator from '../components/Separator'; import classList from '../utils/classList'; +import type * as Component from '../Component'; -function isSeparator(item): boolean { +function isSeparator(item: Mithril.Children): boolean { return item.tag === Separator; } -function withoutUnnecessarySeparators(items: Array): Array { - const newItems = []; - let prevItem; +function withoutUnnecessarySeparators(items: Mithril.Children): Mithril.Children { + const newItems: Mithril.Children = []; + let prevItem: Mithril.Child; items.filter(Boolean).forEach((item: Mithril.Vnode, i: number) => { if (!isSeparator(item) || (prevItem && !isSeparator(prevItem) && i !== items.length - 1)) { @@ -20,17 +21,36 @@ function withoutUnnecessarySeparators(items: Array): Array = Mithril.Vnode | {}> & { + itemName?: string; + itemClassName?: string; +}; + /** - * The `listItems` helper wraps a collection of components in
  • tags, + * The `listItems` helper wraps an array of components in the provided tag, * stripping out any unnecessary `Separator` components. + * + * By default, this tag is an `
  • ` tag, but this is customisable through the + * second function parameter, `customTag`. */ -export default function listItems(items: Mithril.Vnode | Array): Array { +export default function listItems>( + items: ModdedVnode | ModdedVnode[], + customTag: string | Component.default = 'li', + attributes: Attrs = {} +): Mithril.Vnode[] { if (!(items instanceof Array)) items = [items]; - return withoutUnnecessarySeparators(items).map((item: Mithril.Vnode) => { - const isListItem = item.tag && item.tag.isListItem; - const active = item.tag && item.tag.isActive && item.tag.isActive(item.attrs); - const className = (item.attrs && item.attrs.itemClassName) || item.itemClassName; + const Tag = customTag; + + return withoutUnnecessarySeparators(items).map((item: ModdedVnode) => { + const isListItem = item.tag?.isListItem; + const active = item.tag?.isActive?.(item.attrs); + const className = item.attrs?.itemClassName || item.itemClassName; if (isListItem) { item.attrs = item.attrs || {}; @@ -41,12 +61,14 @@ export default function listItems(items: Mithril.Vnode | Array): const node: Mithril.Vnode = isListItem ? ( item ) : ( -
  • {item} -
  • + ); return node;