From ea25ad29ba5d3a97eebadbbbafe560b0c3e01a3c Mon Sep 17 00:00:00 2001 From: Alexander Filatov Date: Wed, 27 Apr 2022 14:32:37 +0400 Subject: [PATCH] Make MenuPlacer component customizable and switchable. --- .changeset/curly-pants-turn.md | 6 +++ docs/examples/CustomMenuPlacer.tsx | 44 +++++++++++++++++++ docs/examples/index.tsx | 1 + docs/pages/components/index.tsx | 20 ++++++++- docs/pages/props/index.tsx | 4 ++ packages/react-select/src/Select.tsx | 2 +- packages/react-select/src/components/Menu.tsx | 2 +- packages/react-select/src/components/index.ts | 4 ++ packages/react-select/src/index.ts | 9 +++- 9 files changed, 88 insertions(+), 4 deletions(-) create mode 100644 .changeset/curly-pants-turn.md create mode 100644 docs/examples/CustomMenuPlacer.tsx diff --git a/.changeset/curly-pants-turn.md b/.changeset/curly-pants-turn.md new file mode 100644 index 0000000000..da8573c635 --- /dev/null +++ b/.changeset/curly-pants-turn.md @@ -0,0 +1,6 @@ +--- +'react-select': patch +'@react-select/docs': patch +--- + +Make "MenuPlacer" component customizable and switchable. diff --git a/docs/examples/CustomMenuPlacer.tsx b/docs/examples/CustomMenuPlacer.tsx new file mode 100644 index 0000000000..a504938cbd --- /dev/null +++ b/docs/examples/CustomMenuPlacer.tsx @@ -0,0 +1,44 @@ +import React, { RefCallback } from 'react'; +import Select, { MenuPlacerProps, PlacerProps } from 'react-select'; +import { + ColourOption, + colourOptions, + FlavourOption, + GroupedOption, + groupedOptions, +} from '../data'; + +const MenuPlacer = ( + props: MenuPlacerProps +) => { + const { children } = props; + + const getCustomPlacement: RefCallback = (ref) => { + if (!ref) return; + // custom implementation of getPlacement + }; + + const getUpdatedProps: () => PlacerProps = () => { + return { + placement: 'top', + maxHeight: 200, + }; + }; + + return ( + <> + {children({ + ref: getCustomPlacement, + placerProps: getUpdatedProps(), + })} + + ); +}; + +export default () => ( + + defaultValue={colourOptions[1]} + options={groupedOptions} + components={{ MenuPlacer }} + /> +); diff --git a/docs/examples/index.tsx b/docs/examples/index.tsx index e8bff14f43..009d4ae31a 100644 --- a/docs/examples/index.tsx +++ b/docs/examples/index.tsx @@ -37,6 +37,7 @@ export { default as CustomSingleValue } from './CustomSingleValue'; export { default as CustomValueContainer } from './CustomValueContainer'; export { default as CustomGetOptionLabel } from './CustomGetOptionLabel'; export { default as CustomGetOptionValue } from './CustomGetOptionValue'; +export { default as CustomMenuPlacer } from './CustomMenuPlacer'; export { default as CustomFilterOptions } from './CustomFilterOptions'; export { default as CustomIsOptionDisabled } from './CustomIsOptionDisabled'; export { default as DefaultOptions } from './DefaultOptions'; diff --git a/docs/pages/components/index.tsx b/docs/pages/components/index.tsx index 5ce78c347e..a6664b6e6b 100644 --- a/docs/pages/components/index.tsx +++ b/docs/pages/components/index.tsx @@ -26,6 +26,7 @@ import { CustomSingleValue, CustomGroupHeading, CustomValueContainer, + CustomMenuPlacer, } from '../../examples'; export default function Components() { @@ -44,7 +45,7 @@ export default function Components() { The main feature of this library is providing consumers with the building blocks necessary to create _their_ component. - The following components are customisable and switchable: + The following components are customizable and switchable: * ClearIndicator * Control * DropdownIndicator @@ -58,6 +59,7 @@ export default function Components() { * LoadingIndicator * Menu * MenuList + * MenuPlacer * MenuPortal * LoadingMessage * NoOptionsMessage @@ -389,6 +391,22 @@ export default function Components() { )} + + ### MenuPlacer + + The wrapper of the Menu. It allows to make custom logic to find the optimal placement of the Menu. + + See [props docs](/props#menuPlacer) for more details + + ${( + + + + )} ### LoadingMessage diff --git a/docs/pages/props/index.tsx b/docs/pages/props/index.tsx index 4b8ee95b18..71128ba995 100644 --- a/docs/pages/props/index.tsx +++ b/docs/pages/props/index.tsx @@ -202,6 +202,10 @@ export default function Api() { ${()} + ### MenuPlacer + + ${()} + ### LoadingMessage ${()} diff --git a/packages/react-select/src/Select.tsx b/packages/react-select/src/Select.tsx index afc2effc04..45e4f6405f 100644 --- a/packages/react-select/src/Select.tsx +++ b/packages/react-select/src/Select.tsx @@ -10,7 +10,6 @@ import { RefCallback, TouchEventHandler, } from 'react'; -import { MenuPlacer } from './components/Menu'; import LiveRegion from './components/LiveRegion'; import { createFilter, FilterOptionOption } from './filters'; @@ -1791,6 +1790,7 @@ export default class Select< Group, GroupHeading, Menu, + MenuPlacer, MenuList, MenuPortal, LoadingMessage, diff --git a/packages/react-select/src/components/Menu.tsx b/packages/react-select/src/components/Menu.tsx index f6846774ec..af6041aa41 100644 --- a/packages/react-select/src/components/Menu.tsx +++ b/packages/react-select/src/components/Menu.tsx @@ -238,7 +238,7 @@ export interface MenuProps< children: ReactNode; } -interface PlacerProps { +export interface PlacerProps { placement: CoercedMenuPlacement; maxHeight: number; } diff --git a/packages/react-select/src/components/index.ts b/packages/react-select/src/components/index.ts index d2c9b84c5e..a735fe0824 100644 --- a/packages/react-select/src/components/index.ts +++ b/packages/react-select/src/components/index.ts @@ -34,6 +34,8 @@ import Menu, { MenuProps, NoOptionsMessage, NoticeProps, + MenuPlacer, + MenuPlacerProps, } from './Menu'; import MultiValue, { MultiValueContainer, @@ -73,6 +75,7 @@ export interface SelectComponents< LoadingIndicatorProps >; Menu: ComponentType>; + MenuPlacer: ComponentType>; MenuList: ComponentType>; MenuPortal: ComponentType>; LoadingMessage: ComponentType>; @@ -113,6 +116,7 @@ export const components = { Input: Input, LoadingIndicator: LoadingIndicator, Menu: Menu, + MenuPlacer: MenuPlacer, MenuList: MenuList, MenuPortal: MenuPortal, LoadingMessage: LoadingMessage, diff --git a/packages/react-select/src/index.ts b/packages/react-select/src/index.ts index 95c2656d8d..1ac38fdb35 100644 --- a/packages/react-select/src/index.ts +++ b/packages/react-select/src/index.ts @@ -31,7 +31,14 @@ export type { LoadingIndicatorProps, } from './components/indicators'; export type { InputProps } from './components/Input'; -export type { MenuListProps, MenuProps, NoticeProps } from './components/Menu'; +export type { + MenuListProps, + MenuProps, + NoticeProps, + MenuPlacerProps, + PlacerProps, +} from './components/Menu'; + export type { MultiValueGenericProps, MultiValueProps,