From 0a015edb9ef57c2869b20dbac1d1debbce7e713a Mon Sep 17 00:00:00 2001 From: Mac Lockard Date: Wed, 20 Oct 2021 09:57:12 -0700 Subject: [PATCH 1/3] Readonly select items prop --- packages/docs-theme/src/components/navigator.tsx | 2 +- packages/select/src/common/itemListRenderer.ts | 4 ++-- packages/select/src/common/listItemsProps.ts | 4 ++-- packages/select/src/common/predicate.ts | 2 +- packages/select/src/components/query-list/queryList.tsx | 4 ++-- packages/select/src/components/select/multiSelect.tsx | 2 +- 6 files changed, 9 insertions(+), 9 deletions(-) diff --git a/packages/docs-theme/src/components/navigator.tsx b/packages/docs-theme/src/components/navigator.tsx index 2d37be7b08..fc8ad9c608 100644 --- a/packages/docs-theme/src/components/navigator.tsx +++ b/packages/docs-theme/src/components/navigator.tsx @@ -85,7 +85,7 @@ export class Navigator extends React.PureComponent { } private filterMatches: ItemListPredicate = (query, items) => - filter(items, query, { + filter([...items], query, { key: "route", maxInners: items.length / 5, maxResults: 10, diff --git a/packages/select/src/common/itemListRenderer.ts b/packages/select/src/common/itemListRenderer.ts index a3c99ea6d3..a5b866d5e4 100644 --- a/packages/select/src/common/itemListRenderer.ts +++ b/packages/select/src/common/itemListRenderer.ts @@ -37,13 +37,13 @@ export interface IItemListRendererProps { * map each item in this array through `renderItem`, with support for * optional `noResults` and `initialContent` states. */ - filteredItems: T[]; + filteredItems: readonly T[]; /** * Array of all items in the list. * See `filteredItems` for a filtered array based on `query` and predicate props. */ - items: T[]; + items: readonly T[]; /** * The current query string. diff --git a/packages/select/src/common/listItemsProps.ts b/packages/select/src/common/listItemsProps.ts index 68caf8a12f..428d68be02 100644 --- a/packages/select/src/common/listItemsProps.ts +++ b/packages/select/src/common/listItemsProps.ts @@ -44,7 +44,7 @@ export interface IListItemsProps extends Props { activeItem?: T | ICreateNewItem | null; /** Array of items in the list. */ - items: T[]; + items: readonly T[]; /** * Specifies how to test if two items are equal. By default, simple strict @@ -155,7 +155,7 @@ export interface IListItemsProps extends Props { /** * Callback invoked when multiple items are selected at once via pasting. */ - onItemsPaste?: (items: T[]) => void; + onItemsPaste?: (items: readonly T[]) => void; /** * Callback invoked when the query string changes. diff --git a/packages/select/src/common/predicate.ts b/packages/select/src/common/predicate.ts index 62624a45b8..40c4148828 100644 --- a/packages/select/src/common/predicate.ts +++ b/packages/select/src/common/predicate.ts @@ -18,7 +18,7 @@ * A custom predicate for returning an entirely new `items` array based on the provided query. * See usage sites in `IListItemsProps`. */ -export type ItemListPredicate = (query: string, items: T[]) => T[]; +export type ItemListPredicate = (query: string, items: readonly T[]) => T[]; /** * A custom predicate for filtering items based on the provided query. diff --git a/packages/select/src/components/query-list/queryList.tsx b/packages/select/src/components/query-list/queryList.tsx index d813930bcf..261bdda2aa 100644 --- a/packages/select/src/components/query-list/queryList.tsx +++ b/packages/select/src/components/query-list/queryList.tsx @@ -134,7 +134,7 @@ export interface IQueryListState { createNewItem: T | undefined; /** The original `items` array filtered by `itemListPredicate` or `itemPredicate`. */ - filteredItems: T[]; + filteredItems: readonly T[]; /** The current query string. */ query: string; @@ -645,7 +645,7 @@ function isItemDisabled(item: T | null, index: number, itemDisabled?: IListIt * @param startIndex which index to begin moving from */ export function getFirstEnabledItem( - items: T[], + items: readonly T[], itemDisabled?: keyof T | ((item: T, index: number) => boolean), direction = 1, startIndex = items.length - 1, diff --git a/packages/select/src/components/select/multiSelect.tsx b/packages/select/src/components/select/multiSelect.tsx index db20c42545..8857d3977b 100644 --- a/packages/select/src/components/select/multiSelect.tsx +++ b/packages/select/src/components/select/multiSelect.tsx @@ -83,7 +83,7 @@ export interface IMultiSelectProps extends IListItemsProps { popoverProps?: Partial & object; /** Controlled selected values. */ - selectedItems?: T[]; + selectedItems?: readonly T[]; /** Props to spread to `TagInput`. Use `query` and `onQueryChange` to control the input. */ // eslint-disable-next-line @typescript-eslint/ban-types From b33006de958925150fdbf0d088968b020217e0c4 Mon Sep 17 00:00:00 2001 From: Mac Lockard Date: Wed, 16 Mar 2022 14:21:51 -0700 Subject: [PATCH 2/3] more type fixes --- .../src/examples/select-examples/multiSelectExample.tsx | 4 ++-- packages/select/src/common/predicate.ts | 2 +- packages/select/test/queryListTests.tsx | 4 +++- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/packages/docs-app/src/examples/select-examples/multiSelectExample.tsx b/packages/docs-app/src/examples/select-examples/multiSelectExample.tsx index 915d4e81e3..b95dd6c4be 100644 --- a/packages/docs-app/src/examples/select-examples/multiSelectExample.tsx +++ b/packages/docs-app/src/examples/select-examples/multiSelectExample.tsx @@ -209,7 +209,7 @@ export class MultiSelectExample extends React.PureComponent { + private handleFilmsPaste = (films: readonly IFilm[]) => { // On paste, don't bother with deselecting already selected values, just // add the new ones. this.selectFilms(films); diff --git a/packages/select/src/common/predicate.ts b/packages/select/src/common/predicate.ts index 40c4148828..094b5db5db 100644 --- a/packages/select/src/common/predicate.ts +++ b/packages/select/src/common/predicate.ts @@ -18,7 +18,7 @@ * A custom predicate for returning an entirely new `items` array based on the provided query. * See usage sites in `IListItemsProps`. */ -export type ItemListPredicate = (query: string, items: readonly T[]) => T[]; +export type ItemListPredicate = (query: string, items: readonly T[]) => readonly T[]; /** * A custom predicate for filtering items based on the provided query. diff --git a/packages/select/test/queryListTests.tsx b/packages/select/test/queryListTests.tsx index 7930bc21c6..642c73f495 100644 --- a/packages/select/test/queryListTests.tsx +++ b/packages/select/test/queryListTests.tsx @@ -85,7 +85,9 @@ describe("", () => { }); it("itemListPredicate filters entire list by query", () => { - const predicate = sinon.spy((query: string, films: IFilm[]) => films.filter(f => f.year === +query)); + const predicate = sinon.spy((query: string, films: readonly IFilm[]) => + films.filter(f => f.year === +query), + ); shallow(); assert.equal(predicate.callCount, 1, "called once for entire list"); From 8fcd017f2bfaf3b2da7b239d8a3b8e3cd3adb401 Mon Sep 17 00:00:00 2001 From: Mac Lockard Date: Thu, 17 Mar 2022 10:06:19 -0700 Subject: [PATCH 3/3] revert breaking changes to callback types. --- .../src/examples/select-examples/multiSelectExample.tsx | 4 ++-- packages/docs-theme/src/components/navigator.tsx | 2 +- packages/select/src/common/itemListRenderer.ts | 4 ++-- packages/select/src/common/listItemsProps.ts | 2 +- packages/select/src/common/predicate.ts | 2 +- packages/select/src/components/query-list/queryList.tsx | 5 +++-- packages/select/test/queryListTests.tsx | 4 +--- 7 files changed, 11 insertions(+), 12 deletions(-) diff --git a/packages/docs-app/src/examples/select-examples/multiSelectExample.tsx b/packages/docs-app/src/examples/select-examples/multiSelectExample.tsx index b95dd6c4be..915d4e81e3 100644 --- a/packages/docs-app/src/examples/select-examples/multiSelectExample.tsx +++ b/packages/docs-app/src/examples/select-examples/multiSelectExample.tsx @@ -209,7 +209,7 @@ export class MultiSelectExample extends React.PureComponent { + private handleFilmsPaste = (films: IFilm[]) => { // On paste, don't bother with deselecting already selected values, just // add the new ones. this.selectFilms(films); diff --git a/packages/docs-theme/src/components/navigator.tsx b/packages/docs-theme/src/components/navigator.tsx index fc8ad9c608..2d37be7b08 100644 --- a/packages/docs-theme/src/components/navigator.tsx +++ b/packages/docs-theme/src/components/navigator.tsx @@ -85,7 +85,7 @@ export class Navigator extends React.PureComponent { } private filterMatches: ItemListPredicate = (query, items) => - filter([...items], query, { + filter(items, query, { key: "route", maxInners: items.length / 5, maxResults: 10, diff --git a/packages/select/src/common/itemListRenderer.ts b/packages/select/src/common/itemListRenderer.ts index a5b866d5e4..a3c99ea6d3 100644 --- a/packages/select/src/common/itemListRenderer.ts +++ b/packages/select/src/common/itemListRenderer.ts @@ -37,13 +37,13 @@ export interface IItemListRendererProps { * map each item in this array through `renderItem`, with support for * optional `noResults` and `initialContent` states. */ - filteredItems: readonly T[]; + filteredItems: T[]; /** * Array of all items in the list. * See `filteredItems` for a filtered array based on `query` and predicate props. */ - items: readonly T[]; + items: T[]; /** * The current query string. diff --git a/packages/select/src/common/listItemsProps.ts b/packages/select/src/common/listItemsProps.ts index 428d68be02..32bc5d327d 100644 --- a/packages/select/src/common/listItemsProps.ts +++ b/packages/select/src/common/listItemsProps.ts @@ -155,7 +155,7 @@ export interface IListItemsProps extends Props { /** * Callback invoked when multiple items are selected at once via pasting. */ - onItemsPaste?: (items: readonly T[]) => void; + onItemsPaste?: (items: T[]) => void; /** * Callback invoked when the query string changes. diff --git a/packages/select/src/common/predicate.ts b/packages/select/src/common/predicate.ts index 094b5db5db..2fb2243980 100644 --- a/packages/select/src/common/predicate.ts +++ b/packages/select/src/common/predicate.ts @@ -18,7 +18,7 @@ * A custom predicate for returning an entirely new `items` array based on the provided query. * See usage sites in `IListItemsProps`. */ -export type ItemListPredicate = (query: string, items: readonly T[]) => readonly T[]; +export type ItemListPredicate = (query: string, items: T[]) => readonly T[]; /** * A custom predicate for filtering items based on the provided query. diff --git a/packages/select/src/components/query-list/queryList.tsx b/packages/select/src/components/query-list/queryList.tsx index 261bdda2aa..b14330e612 100644 --- a/packages/select/src/components/query-list/queryList.tsx +++ b/packages/select/src/components/query-list/queryList.tsx @@ -218,7 +218,8 @@ export class QueryList extends AbstractComponent2, IQueryLi handleQueryChange: this.handleInputQueryChange, itemList: itemListRenderer({ ...spreadableState, - items, + filteredItems: spreadableState.filteredItems.slice(), + items: items.slice(), itemsParentRef: this.refHandlers.itemsParent, renderCreateItem: this.renderCreateItemMenuItem, renderItem: this.renderItem, @@ -609,7 +610,7 @@ function getMatchingItem(query: string, { items, itemPredicate }: QueryListPr function getFilteredItems(query: string, { items, itemPredicate, itemListPredicate }: QueryListProps) { if (Utils.isFunction(itemListPredicate)) { // note that implementations can reorder the items here - return itemListPredicate(query, items); + return itemListPredicate(query, items.slice()); } else if (Utils.isFunction(itemPredicate)) { return items.filter((item, index) => itemPredicate(query, item, index)); } diff --git a/packages/select/test/queryListTests.tsx b/packages/select/test/queryListTests.tsx index 642c73f495..7930bc21c6 100644 --- a/packages/select/test/queryListTests.tsx +++ b/packages/select/test/queryListTests.tsx @@ -85,9 +85,7 @@ describe("", () => { }); it("itemListPredicate filters entire list by query", () => { - const predicate = sinon.spy((query: string, films: readonly IFilm[]) => - films.filter(f => f.year === +query), - ); + const predicate = sinon.spy((query: string, films: IFilm[]) => films.filter(f => f.year === +query)); shallow(); assert.equal(predicate.callCount, 1, "called once for entire list");