Skip to content

Commit

Permalink
Update examples and tests to use readonly array
Browse files Browse the repository at this point in the history
  • Loading branch information
ggdouglas committed Oct 30, 2024
1 parent 8f5925a commit af3c19a
Show file tree
Hide file tree
Showing 8 changed files with 42 additions and 38 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: Film[];
createdItems: readonly Film[];
disabled: boolean;
fill: boolean;
films: Film[];
films: readonly Film[];
hasInitialContent: boolean;
intent: boolean;
items: Film[];
items: readonly 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<Film>
<MultiSelect
{...flags}
createNewItemFromQuery={allowCreate ? createFilms : undefined}
createNewItemRenderer={allowCreate ? renderCreateFilmsMenuItem : null}
Expand Down Expand Up @@ -251,7 +251,9 @@ export class MultiSelectExample extends React.PureComponent<ExampleProps, MultiS
);
}

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

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

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

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

filmsToSelect.forEach(film => {
const results = maybeAddCreatedFilmToArrays(nextItems, nextCreatedItems, film);
nextItems = results.items;
nextCreatedItems = results.createdItems;
nextItems = results.items.slice();
nextCreatedItems = results.createdItems.slice();
// Avoid re-creating an item that is already selected (the "Create
// Item" option will be shown even if it matches an already selected
// item).
Expand Down Expand Up @@ -336,7 +338,7 @@ export class MultiSelectExample extends React.PureComponent<ExampleProps, MultiS
}
};

private handleFilmsPaste = (films: Film[]) => {
private handleFilmsPaste = (films: readonly 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<Film>
<Omnibar
{...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: Film[];
createdItems: readonly 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: Film[]) => {
private getGroupedItems = (filteredItems: readonly 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: Film[]) => {
private groupedItemListPredicate = (query: string, items: readonly 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>) => {
private renderGroupedItemList = (listProps: ItemListRendererProps<Film, readonly 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>,
listProps: ItemListRendererProps<Film, readonly 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: Film[];
createdItems: readonly Film[];
disabled: boolean;
fill: boolean;
items: Film[];
items: readonly 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<Film>
<Suggest
{...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>,
SelectProps<Film, readonly 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([...TOP_100_FILMS]);
const [createdItems, setCreatedItems] = React.useState<Film[]>([]);
const [items, setItems] = React.useState<readonly Film[]>([...TOP_100_FILMS]);
const [createdItems, setCreatedItems] = React.useState<readonly 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<Film>
<Select
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: Film[] = [
export const TOP_100_FILMS: readonly 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): Film[] {
export function createFilms(query: string): readonly 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: Film[], filmToFind: Film): boolean {
export function arrayContainsFilm(films: readonly Film[], filmToFind: Film): boolean {
return films.some((film: Film) => film.title === filmToFind.title);
}

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

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

export function maybeAddCreatedFilmToArrays(
items: Film[],
createdItems: Film[],
items: readonly Film[],
createdItems: readonly Film[],
film: Film,
): { createdItems: Film[]; items: Film[] } {
): { createdItems: readonly Film[]; items: readonly 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: Film[],
createdItems: Film[],
items: readonly Film[],
createdItems: readonly Film[],
film: Film | undefined,
): { createdItems: Film[]; items: Film[] } {
): { createdItems: readonly Film[]; items: readonly Film[] } {
if (film === undefined) {
return {
createdItems,
Expand Down
8 changes: 4 additions & 4 deletions packages/select/test/multiSelectTests.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ describe("<MultiSelect>", () => {
items: TOP_100_FILMS,
popoverProps: { isOpen: true, usePortal: false },
query: "",
selectedItems: [] as Film[],
selectedItems: [] as readonly Film[],
tagRenderer: renderTag,
};
let handlers: {
Expand Down Expand Up @@ -135,7 +135,7 @@ describe("<MultiSelect>", () => {
popoverProps: { usePortal: false },
};

const wrapper = mount(<MultiSelect<Film> {...defaultProps} {...handlers} {...props} />, {
const wrapper = mount(<MultiSelect {...defaultProps} {...handlers} {...props} />, {
attachTo: containerElement,
});

Expand Down Expand Up @@ -167,9 +167,9 @@ describe("<MultiSelect>", () => {
containerElement?.remove();
});

function multiselect(props: Partial<MultiSelectProps<Film>> = {}, query?: string) {
function multiselect(props: Partial<MultiSelectProps<Film, readonly Film[]>> = {}, query?: string) {
const wrapper = mount(
<MultiSelect<Film> {...defaultProps} {...handlers} {...props}>
<MultiSelect {...defaultProps} {...handlers} {...props}>
<article />
</MultiSelect>,
);
Expand Down
4 changes: 3 additions & 1 deletion packages/select/test/queryListTests.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,9 @@ describe("<QueryList>", () => {
});

it("itemListPredicate filters entire list by query", () => {
const predicate = sinon.spy((query: string, films: Film[]) => films.filter(f => f.year === +query));
const predicate = sinon.spy((query: string, films: readonly Film[]) =>
films.filter(f => f.year === +query),
);
shallow(<QueryList<Film> {...testProps} itemListPredicate={predicate} query="1994" />);

assert.equal(predicate.callCount, 1, "called once for entire list");
Expand Down

0 comments on commit af3c19a

Please sign in to comment.