From 97babd0f6065786857b534ba538bbdbce198ec00 Mon Sep 17 00:00:00 2001 From: David Wheatley Date: Tue, 2 Nov 2021 19:36:08 +0000 Subject: [PATCH 1/5] feat: allow use of any tag in `listItems` helper --- js/src/common/helpers/listItems.tsx | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/js/src/common/helpers/listItems.tsx b/js/src/common/helpers/listItems.tsx index 218b353c99..59ee02f638 100644 --- a/js/src/common/helpers/listItems.tsx +++ b/js/src/common/helpers/listItems.tsx @@ -1,6 +1,7 @@ import type Mithril from 'mithril'; import Separator from '../components/Separator'; import classList from '../utils/classList'; +import type Component from '../Component'; function isSeparator(item): boolean { return item.tag === Separator; @@ -21,12 +22,21 @@ function withoutUnnecessarySeparators(items: Array): Array 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: Mithril.Vnode | Mithril.Vnode[], + customTag: string | Component = 'li', + attributes: Attrs = {} +): Mithril.Vnode[] { if (!(items instanceof Array)) items = [items]; + const Tag = customTag; + 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); @@ -41,12 +51,13 @@ export default function listItems(items: Mithril.Vnode | Array): const node: Mithril.Vnode = isListItem ? ( item ) : ( -
  • {item} -
  • + ); return node; From 977564a15c5bfd818a2d06668f795501a83ee5e3 Mon Sep 17 00:00:00 2001 From: David Wheatley Date: Tue, 2 Nov 2021 19:59:34 +0000 Subject: [PATCH 2/5] fix: fix missing optional chaining --- js/src/common/helpers/listItems.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/src/common/helpers/listItems.tsx b/js/src/common/helpers/listItems.tsx index 59ee02f638..d70ab23323 100644 --- a/js/src/common/helpers/listItems.tsx +++ b/js/src/common/helpers/listItems.tsx @@ -53,7 +53,7 @@ export default function listItems>( ) : ( {item} From 6d3eadd954bed10391582600741b977e95e5dcd3 Mon Sep 17 00:00:00 2001 From: David Wheatley Date: Tue, 2 Nov 2021 20:04:44 +0000 Subject: [PATCH 3/5] chore: use more optional chaining --- js/src/common/helpers/listItems.tsx | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/js/src/common/helpers/listItems.tsx b/js/src/common/helpers/listItems.tsx index d70ab23323..b9b44d7cd0 100644 --- a/js/src/common/helpers/listItems.tsx +++ b/js/src/common/helpers/listItems.tsx @@ -1,7 +1,7 @@ import type Mithril from 'mithril'; import Separator from '../components/Separator'; import classList from '../utils/classList'; -import type Component from '../Component'; +import type * as Component from '../Component'; function isSeparator(item): boolean { return item.tag === Separator; @@ -28,9 +28,9 @@ function withoutUnnecessarySeparators(items: Array): Array` tag, but this is customisable through the * second function parameter, `customTag`. */ -export default function listItems>( +export default function listItems>( items: Mithril.Vnode | Mithril.Vnode[], - customTag: string | Component = 'li', + customTag: string | Component.default = 'li', attributes: Attrs = {} ): Mithril.Vnode[] { if (!(items instanceof Array)) items = [items]; @@ -38,9 +38,9 @@ export default function listItems>( const Tag = customTag; 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 isListItem = item.tag?.isListItem; + const active = item.tag?.isActive?.(item.attrs); + const className = item.attrs?.itemClassName || item.itemClassName; if (isListItem) { item.attrs = item.attrs || {}; From 40bfbcd873e6a8d8658c06d6d7d48b1499996c8c Mon Sep 17 00:00:00 2001 From: David Wheatley Date: Tue, 2 Nov 2021 20:11:38 +0000 Subject: [PATCH 4/5] fix: various typings errors --- js/src/common/helpers/listItems.tsx | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/js/src/common/helpers/listItems.tsx b/js/src/common/helpers/listItems.tsx index b9b44d7cd0..5bdfa935bb 100644 --- a/js/src/common/helpers/listItems.tsx +++ b/js/src/common/helpers/listItems.tsx @@ -3,13 +3,13 @@ import Separator from '../components/Separator'; import classList from '../utils/classList'; import type * as Component from '../Component'; -function isSeparator(item): boolean { +function isSeparator(item: Mithril.Vnode): boolean { return item.tag === Separator; } -function withoutUnnecessarySeparators(items: Array): Array { - const newItems = []; - let prevItem; +function withoutUnnecessarySeparators(items: Mithril.Vnode[]): Mithril.Vnode[] { + const newItems: Mithril.Vnode[] = []; + let prevItem: Mithril.Vnode; items.filter(Boolean).forEach((item: Mithril.Vnode, i: number) => { if (!isSeparator(item) || (prevItem && !isSeparator(prevItem) && i !== items.length - 1)) { @@ -21,6 +21,16 @@ function withoutUnnecessarySeparators(items: Array): Array = Mithril.Vnode | {}> & { + itemName?: string; + itemClassName?: string; +}; + /** * The `listItems` helper wraps an array of components in the provided tag, * stripping out any unnecessary `Separator` components. @@ -29,7 +39,7 @@ function withoutUnnecessarySeparators(items: Array): Array>( - items: Mithril.Vnode | Mithril.Vnode[], + items: ModdedVnode | ModdedVnode[], customTag: string | Component.default = 'li', attributes: Attrs = {} ): Mithril.Vnode[] { @@ -37,7 +47,7 @@ export default function listItems>( const Tag = customTag; - return withoutUnnecessarySeparators(items).map((item: Mithril.Vnode) => { + 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; @@ -51,6 +61,7 @@ export default function listItems>( const node: Mithril.Vnode = isListItem ? ( item ) : ( + // @ts-expect-error `Component` does not have any construct or call signatures Date: Wed, 3 Nov 2021 23:02:06 +0100 Subject: [PATCH 5/5] chore: replace `Vnode[]` with `Children` --- js/src/common/helpers/listItems.tsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/js/src/common/helpers/listItems.tsx b/js/src/common/helpers/listItems.tsx index 5bdfa935bb..078f868bd9 100644 --- a/js/src/common/helpers/listItems.tsx +++ b/js/src/common/helpers/listItems.tsx @@ -3,13 +3,13 @@ import Separator from '../components/Separator'; import classList from '../utils/classList'; import type * as Component from '../Component'; -function isSeparator(item: Mithril.Vnode): boolean { +function isSeparator(item: Mithril.Children): boolean { return item.tag === Separator; } -function withoutUnnecessarySeparators(items: Mithril.Vnode[]): Mithril.Vnode[] { - const newItems: Mithril.Vnode[] = []; - let prevItem: Mithril.Vnode; +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)) {