diff --git a/packages/docs-app/src/examples/select-examples/films.tsx b/packages/docs-app/src/examples/select-examples/films.tsx index a92fd3dafc..04723365f2 100644 --- a/packages/docs-app/src/examples/select-examples/films.tsx +++ b/packages/docs-app/src/examples/select-examples/films.tsx @@ -138,6 +138,20 @@ export const renderFilm: ItemRenderer = (film, { handleClick, modifiers, ); }; +export const renderCreateFilmOption = ( + query: string, + active: boolean, + handleClick: React.MouseEventHandler, +) => ( + +); + export const filterFilm: ItemPredicate = (query, film) => { return `${film.rank}. ${film.title.toLowerCase()} ${film.year}`.indexOf(query.toLowerCase()) >= 0; }; @@ -182,3 +196,55 @@ export const filmSelectProps = { itemRenderer: renderFilm, items: TOP_100_FILMS, }; + +export function createFilm(title: string): IFilm { + return { + rank: 100 + Math.floor(Math.random() * 100 + 1), + title, + year: new Date().getFullYear(), + }; +} + +export function areFilmsEqual(filmA: IFilm, filmB: IFilm) { + // Compare only the titles (ignoring case) just for simplicity. + return filmA.title.toLowerCase() === filmB.title.toLowerCase(); +} + +export function arrayContainsFilm(films: IFilm[], filmToFind: IFilm): boolean { + return films.some((film: IFilm) => film.title === filmToFind.title); +} + +export function addFilmToArray(films: IFilm[], filmToAdd: IFilm) { + return [...films, filmToAdd]; +} + +export function deleteFilmFromArray(films: IFilm[], filmToDelete: IFilm) { + return films.filter(film => film !== filmToDelete); +} + +export function maybeAddCreatedFilmToArrays( + items: IFilm[], + createdItems: IFilm[], + film: IFilm, +): { createdItems: IFilm[]; items: IFilm[] } { + const isNewlyCreatedItem = !arrayContainsFilm(items, film); + return { + createdItems: isNewlyCreatedItem ? addFilmToArray(createdItems, film) : createdItems, + // Add a created film to `items` so that the film can be deselected. + items: isNewlyCreatedItem ? addFilmToArray(items, film) : items, + }; +} + +export function maybeDeleteCreatedFilmFromArrays( + items: IFilm[], + createdItems: IFilm[], + film: IFilm, +): { createdItems: IFilm[]; items: IFilm[] } { + const wasItemCreatedByUser = arrayContainsFilm(createdItems, film); + + // Delete the item if the user manually created it. + return { + createdItems: wasItemCreatedByUser ? deleteFilmFromArray(createdItems, film) : createdItems, + items: wasItemCreatedByUser ? deleteFilmFromArray(items, film) : items, + }; +} diff --git a/packages/docs-app/src/examples/select-examples/multiSelectExample.tsx b/packages/docs-app/src/examples/select-examples/multiSelectExample.tsx index 54e45770a9..8f138d3cb7 100644 --- a/packages/docs-app/src/examples/select-examples/multiSelectExample.tsx +++ b/packages/docs-app/src/examples/select-examples/multiSelectExample.tsx @@ -9,16 +9,29 @@ import * as React from "react"; import { Button, H5, Intent, ITagProps, MenuItem, Switch } from "@blueprintjs/core"; import { Example, IExampleProps } from "@blueprintjs/docs-theme"; import { ItemRenderer, MultiSelect } from "@blueprintjs/select"; -import { filmSelectProps, IFilm, TOP_100_FILMS } from "./films"; +import { + areFilmsEqual, + arrayContainsFilm, + createFilm, + filmSelectProps, + IFilm, + maybeAddCreatedFilmToArrays, + maybeDeleteCreatedFilmFromArrays, + renderCreateFilmOption, + TOP_100_FILMS, +} from "./films"; const FilmMultiSelect = MultiSelect.ofType(); const INTENTS = [Intent.NONE, Intent.PRIMARY, Intent.SUCCESS, Intent.DANGER, Intent.WARNING]; export interface IMultiSelectExampleState { + allowCreate: boolean; + createdItems: IFilm[]; films: IFilm[]; hasInitialContent: boolean; intent: boolean; + items: IFilm[]; openOnKeyDown: boolean; popoverMinimal: boolean; resetOnSelect: boolean; @@ -27,15 +40,19 @@ export interface IMultiSelectExampleState { export class MultiSelectExample extends React.PureComponent { public state: IMultiSelectExampleState = { + allowCreate: false, + createdItems: [], films: [], hasInitialContent: false, intent: false, + items: filmSelectProps.items, openOnKeyDown: false, popoverMinimal: true, resetOnSelect: true, tagMinimal: false, }; + private handleAllowCreateChange = this.handleSwitchChange("allowCreate"); private handleKeyDownChange = this.handleSwitchChange("openOnKeyDown"); private handleResetChange = this.handleSwitchChange("resetOnSelect"); private handlePopoverMinimalChange = this.handleSwitchChange("popoverMinimal"); @@ -44,7 +61,7 @@ export class MultiSelectExample extends React.PureComponent ({ intent: this.state.intent ? INTENTS[index % INTENTS.length] : Intent.NONE, minimal: tagMinimal, @@ -56,6 +73,8 @@ export class MultiSelectExample extends React.PureComponent 0 ?