Skip to content

Commit

Permalink
Revert "Use generics for Select arrays (#7036)"
Browse files Browse the repository at this point in the history
This reverts commit 4d1297a.
  • Loading branch information
jscheiny committed Nov 5, 2024
1 parent 265df1a commit 5de0a28
Show file tree
Hide file tree
Showing 19 changed files with 116 additions and 143 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,13 @@ const INTENTS = [Intent.NONE, Intent.PRIMARY, Intent.SUCCESS, Intent.DANGER, Int

export interface MultiSelectExampleState {
allowCreate: boolean;
createdItems: readonly Film[];
createdItems: Film[];
disabled: boolean;
fill: boolean;
films: readonly Film[];
films: Film[];
hasInitialContent: boolean;
intent: boolean;
items: readonly Film[];
items: Film[];
matchTargetWidth: boolean;
openOnKeyDown: boolean;
popoverMinimal: boolean;
Expand Down Expand Up @@ -124,7 +124,7 @@ export class MultiSelectExample extends React.PureComponent<ExampleProps, MultiS

return (
<Example options={this.renderOptions()} {...this.props}>
<MultiSelect
<MultiSelect<Film>
{...flags}
createNewItemFromQuery={allowCreate ? createFilms : undefined}
createNewItemRenderer={allowCreate ? renderCreateFilmsMenuItem : null}
Expand Down Expand Up @@ -251,9 +251,7 @@ export class MultiSelectExample extends React.PureComponent<ExampleProps, MultiS
);
}

private renderCustomTarget = (selectedItems: readonly Film[]) => (
<MultiSelectCustomTarget count={selectedItems.length} />
);
private renderCustomTarget = (selectedItems: Film[]) => <MultiSelectCustomTarget count={selectedItems.length} />;

private renderTag = (film: Film) => film.title;

Expand Down Expand Up @@ -289,11 +287,11 @@ export class MultiSelectExample extends React.PureComponent<ExampleProps, MultiS
this.selectFilms([film]);
}

private selectFilms(filmsToSelect: readonly Film[]) {
private selectFilms(filmsToSelect: Film[]) {
this.setState(({ createdItems, films, items }) => {
let nextCreatedItems = createdItems;
let nextFilms = films;
let nextItems = items;
let nextCreatedItems = createdItems.slice();
let nextFilms = films.slice();
let nextItems = items.slice();

filmsToSelect.forEach(film => {
const results = maybeAddCreatedFilmToArrays(nextItems, nextCreatedItems, film);
Expand Down Expand Up @@ -338,7 +336,7 @@ export class MultiSelectExample extends React.PureComponent<ExampleProps, MultiS
}
};

private handleFilmsPaste = (films: readonly Film[]) => {
private handleFilmsPaste = (films: Film[]) => {
// On paste, don't bother with deselecting already selected values, just
// add the new ones.
this.selectFilms(films);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ export class OmnibarExample extends React.PureComponent<ExampleProps, OmnibarExa
<KeyComboTag combo="shift + o" />
</span>

<Omnibar
<Omnibar<Film>
{...this.state}
createNewItemFromQuery={maybeCreateNewItemFromQuery}
createNewItemRenderer={maybeCreateNewItemRenderer}
Expand Down
10 changes: 5 additions & 5 deletions packages/docs-app/src/examples/select-examples/selectExample.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import { type Film, FilmSelect, filterFilm, TOP_100_FILMS } from "@blueprintjs/s
export interface SelectExampleState {
allowCreate: boolean;
createFirst: boolean;
createdItems: readonly Film[];
createdItems: Film[];
disableItems: boolean;
disabled: boolean;
fill: boolean;
Expand Down Expand Up @@ -169,7 +169,7 @@ export class SelectExample extends React.PureComponent<ExampleProps, SelectExamp
return /[0-9]/.test(firstLetter) ? "0-9" : firstLetter;
}

private getGroupedItems = (filteredItems: readonly Film[]) => {
private getGroupedItems = (filteredItems: Film[]) => {
return filteredItems.reduce<Array<{ group: string; index: number; items: Film[]; key: number }>>(
(acc, item, index) => {
const group = this.getGroup(item);
Expand All @@ -193,7 +193,7 @@ export class SelectExample extends React.PureComponent<ExampleProps, SelectExamp
) : undefined;
};

private groupedItemListPredicate = (query: string, items: readonly Film[]) => {
private groupedItemListPredicate = (query: string, items: Film[]) => {
return items
.filter((item, index) => filterFilm(query, item, index))
.sort((a, b) => this.getGroup(a).localeCompare(this.getGroup(b)));
Expand All @@ -208,7 +208,7 @@ export class SelectExample extends React.PureComponent<ExampleProps, SelectExamp

private isItemDisabled = (film: Film) => this.state.disableItems && film.year < 2000;

private renderGroupedItemList = (listProps: ItemListRendererProps<Film, readonly Film[]>) => {
private renderGroupedItemList = (listProps: ItemListRendererProps<Film>) => {
const initialContent = this.getInitialContent();
const noResults = <MenuItem disabled={true} text="No results." roleStructure="listoption" />;

Expand All @@ -231,7 +231,7 @@ export class SelectExample extends React.PureComponent<ExampleProps, SelectExamp
};

private renderGroupedMenuContent = (
listProps: ItemListRendererProps<Film, readonly Film[]>,
listProps: ItemListRendererProps<Film>,
noResults?: React.ReactNode,
initialContent?: React.ReactNode | null,
) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,10 @@ import {
export interface SuggestExampleState {
allowCreate: boolean;
closeOnSelect: boolean;
createdItems: readonly Film[];
createdItems: Film[];
disabled: boolean;
fill: boolean;
items: readonly Film[];
items: Film[];
matchTargetWidth: boolean;
minimal: boolean;
openOnKeyDown: boolean;
Expand Down Expand Up @@ -92,7 +92,7 @@ export class SuggestExample extends React.PureComponent<ExampleProps, SuggestExa

return (
<Example options={this.renderOptions()} {...this.props}>
<Suggest
<Suggest<Film>
{...flags}
createNewItemFromQuery={maybeCreateNewItemFromQuery}
createNewItemRenderer={maybeCreateNewItemRenderer}
Expand Down
8 changes: 4 additions & 4 deletions packages/select/src/__examples__/filmSelect.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ import {
} from "./films";

type FilmSelectProps = Omit<
SelectProps<Film, readonly Film[]>,
SelectProps<Film>,
| "createNewItemFromQuery"
| "createNewItemRenderer"
| "itemPredicate"
Expand All @@ -49,8 +49,8 @@ type FilmSelectProps = Omit<
};

export function FilmSelect({ allowCreate = false, fill, ...restProps }: FilmSelectProps) {
const [items, setItems] = React.useState<readonly Film[]>([...TOP_100_FILMS]);
const [createdItems, setCreatedItems] = React.useState<readonly Film[]>([]);
const [items, setItems] = React.useState([...TOP_100_FILMS]);
const [createdItems, setCreatedItems] = React.useState<Film[]>([]);
const [selectedFilm, setSelectedFilm] = React.useState<Film | undefined>(undefined);
const handleItemSelect = React.useCallback(
(newFilm: Film) => {
Expand Down Expand Up @@ -82,7 +82,7 @@ export function FilmSelect({ allowCreate = false, fill, ...restProps }: FilmSele
);

return (
<Select
<Select<Film>
createNewItemFromQuery={allowCreate ? createFilm : undefined}
createNewItemRenderer={allowCreate ? renderCreateFilmMenuItem : undefined}
fill={fill}
Expand Down
22 changes: 11 additions & 11 deletions packages/select/src/__examples__/films.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export interface Film {
}

/** Top 100 films as rated by IMDb users. http://www.imdb.com/chart/top */
export const TOP_100_FILMS: readonly Film[] = [
export const TOP_100_FILMS: Film[] = [
{ title: "The Shawshank Redemption", year: 1994 },
{ title: "The Godfather", year: 1972 },
{ title: "The Godfather: Part II", year: 1974 },
Expand Down Expand Up @@ -270,7 +270,7 @@ export function createFilm(title: string): Film {
};
}

export function createFilms(query: string): readonly Film[] {
export function createFilms(query: string): Film[] {
const titles = query.split(", ");
return titles.map((title, index) => ({
rank: 100 + Math.floor(Math.random() * 100 + index),
Expand All @@ -288,23 +288,23 @@ export function doesFilmEqualQuery(film: Film, query: string) {
return film.title.toLowerCase() === query.toLowerCase();
}

export function arrayContainsFilm(films: readonly Film[], filmToFind: Film): boolean {
export function arrayContainsFilm(films: Film[], filmToFind: Film): boolean {
return films.some((film: Film) => film.title === filmToFind.title);
}

export function addFilmToArray(films: readonly Film[], filmToAdd: Film): readonly Film[] {
export function addFilmToArray(films: Film[], filmToAdd: Film) {
return [...films, filmToAdd];
}

export function deleteFilmFromArray(films: readonly Film[], filmToDelete: Film): readonly Film[] {
export function deleteFilmFromArray(films: Film[], filmToDelete: Film) {
return films.filter(film => film !== filmToDelete);
}

export function maybeAddCreatedFilmToArrays(
items: readonly Film[],
createdItems: readonly Film[],
items: Film[],
createdItems: Film[],
film: Film,
): { createdItems: readonly Film[]; items: readonly Film[] } {
): { createdItems: Film[]; items: Film[] } {
const isNewlyCreatedItem = !arrayContainsFilm(items, film);
return {
createdItems: isNewlyCreatedItem ? addFilmToArray(createdItems, film) : createdItems,
Expand All @@ -314,10 +314,10 @@ export function maybeAddCreatedFilmToArrays(
}

export function maybeDeleteCreatedFilmFromArrays(
items: readonly Film[],
createdItems: readonly Film[],
items: Film[],
createdItems: Film[],
film: Film | undefined,
): { createdItems: readonly Film[]; items: readonly Film[] } {
): { createdItems: Film[]; items: Film[] } {
if (film === undefined) {
return {
createdItems,
Expand Down
14 changes: 6 additions & 8 deletions packages/select/src/common/itemListRenderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import type { CreateNewItem } from "./listItemsUtils";
* An object describing how to render the list of items.
* An `itemListRenderer` receives this object as its sole argument.
*/
export interface ItemListRendererProps<T, A extends readonly T[] = T[]> {
export interface ItemListRendererProps<T> {
/**
* The currently focused item (for keyboard interactions), or `null` to
* indicate that no item is active.
Expand All @@ -35,13 +35,13 @@ export interface ItemListRendererProps<T, A extends readonly T[] = T[]> {
* map each item in this array through `renderItem`, with support for
* optional `noResults` and `initialContent` states.
*/
filteredItems: A;
filteredItems: T[];

/**
* Array of all items in the list.
* See `filteredItems` for a filtered array based on `query` and predicate props.
*/
items: A;
items: T[];

/**
* The current query string.
Expand Down Expand Up @@ -75,17 +75,15 @@ export interface ItemListRendererProps<T, A extends readonly T[] = T[]> {
}

/** Type alias for a function that renders the list of items. */
export type ItemListRenderer<T, A extends readonly T[] = T[]> = (
itemListProps: ItemListRendererProps<T, A>,
) => React.JSX.Element | null;
export type ItemListRenderer<T> = (itemListProps: ItemListRendererProps<T>) => React.JSX.Element | null;

/**
* `ItemListRenderer` helper method for rendering each item in `filteredItems`,
* with optional support for `noResults` (when filtered items is empty)
* and `initialContent` (when query is empty).
*/
export function renderFilteredItems<T, A extends readonly T[] = T[]>(
props: ItemListRendererProps<T, A>,
export function renderFilteredItems(
props: ItemListRendererProps<any>,
noResults?: React.ReactNode,
initialContent?: React.ReactNode | null,
): React.ReactNode {
Expand Down
12 changes: 6 additions & 6 deletions packages/select/src/common/listItemsProps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ export type ItemsEqualComparator<T> = (itemA: T, itemB: T) => boolean;
export type ItemsEqualProp<T> = ItemsEqualComparator<T> | keyof T;

/** Reusable generic props for a component that operates on a filterable, selectable list of `items`. */
export interface ListItemsProps<T, A extends readonly T[] = T[]> extends Props {
export interface ListItemsProps<T> extends Props {
/**
* The currently focused item for keyboard interactions, or `null` to
* indicate that no item is active. If omitted or `undefined`, this prop will be
Expand All @@ -44,7 +44,7 @@ export interface ListItemsProps<T, A extends readonly T[] = T[]> extends Props {
activeItem?: T | CreateNewItem | null;

/** Array of items in the list. */
items: A;
items: T[];

/**
* Specifies how to test if two items are equal. By default, simple strict
Expand Down Expand Up @@ -75,7 +75,7 @@ export interface ListItemsProps<T, A extends readonly T[] = T[]> extends Props {
*
* If `itemPredicate` is also defined, this prop takes priority and the other will be ignored.
*/
itemListPredicate?: ItemListPredicate<T, A>;
itemListPredicate?: ItemListPredicate<T>;

/**
* Customize querying of individual items.
Expand Down Expand Up @@ -110,7 +110,7 @@ export interface ListItemsProps<T, A extends readonly T[] = T[]> extends Props {
* and wraps them all in a `Menu` element. If the query is empty then `initialContent` is returned,
* and if there are no items that match the predicate then `noResults` is returned.
*/
itemListRenderer?: ItemListRenderer<T, A>;
itemListRenderer?: ItemListRenderer<T>;

/**
* React content to render when query is empty.
Expand Down Expand Up @@ -157,7 +157,7 @@ export interface ListItemsProps<T, A extends readonly T[] = T[]> extends Props {
/**
* Callback invoked when multiple items are selected at once via pasting.
*/
onItemsPaste?: (items: A) => void;
onItemsPaste?: (items: T[]) => void;

/**
* Callback invoked when the query string changes.
Expand All @@ -170,7 +170,7 @@ export interface ListItemsProps<T, A extends readonly T[] = T[]> extends Props {
* created, either by pressing the `Enter` key or by clicking on the "Create
* Item" option. It transforms a query string into one or many items type.
*/
createNewItemFromQuery?: (query: string) => T | A;
createNewItemFromQuery?: (query: string) => T | T[];

/**
* Custom renderer to transform the current query string into a selectable
Expand Down
2 changes: 1 addition & 1 deletion packages/select/src/common/predicate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
* A custom predicate for returning an entirely new `items` array based on the provided query.
* See usage sites in `ListItemsProps`.
*/
export type ItemListPredicate<T, A extends readonly T[] = T[]> = (query: string, items: A) => A;
export type ItemListPredicate<T> = (query: string, items: T[]) => T[];

/**
* A custom predicate for filtering items based on the provided query.
Expand Down
Loading

1 comment on commit 5de0a28

@svc-palantir-github
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Revert "Use generics for Select arrays (#7036)"

Build artifact links for this commit: documentation | landing | table | demo

This is an automated comment from the deploy-preview CircleCI job.

Please sign in to comment.